diff options
Diffstat (limited to 'drivers/media/i2c')
41 files changed, 1110 insertions, 691 deletions
| diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index ce9006e10a30..2669b4bad910 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -21,7 +21,7 @@ config VIDEO_IR_I2C  # Encoder / Decoder module configuration  # -menu "Encoders, decoders, sensors and other helper chips" +menu "I2C Encoders, decoders, sensors and other helper chips"  	visible if !MEDIA_SUBDRV_AUTOSELECT || COMPILE_TEST  comment "Audio decoders, processors and mixers" @@ -187,7 +187,7 @@ comment "Video decoders"  config VIDEO_ADV7180  	tristate "Analog Devices ADV7180 decoder" -	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API +	depends on GPIOLIB && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API  	---help---  	  Support for the Analog Devices ADV7180 video decoder. @@ -295,6 +295,13 @@ config VIDEO_ML86V7667  	  To compile this driver as a module, choose M here: the  	  module will be called ml86v7667. +config VIDEO_AD5820 +	tristate "AD5820 lens voice coil support" +	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER +	---help--- +	  This is a driver for the AD5820 camera lens voice coil. +	  It is used for example in Nokia N900 (RX-51). +  config VIDEO_SAA7110  	tristate "Philips SAA7110 video decoder"  	depends on VIDEO_V4L2 && I2C @@ -571,6 +578,13 @@ config VIDEO_MT9M032  	  This driver supports MT9M032 camera sensors from Aptina, monochrome  	  models only. +config VIDEO_MT9M111 +	tristate "mt9m111, mt9m112 and mt9m131 support" +	depends on I2C && VIDEO_V4L2 +	help +	  This driver supports MT9M111, MT9M112 and MT9M131 cameras from +	  Micron/Aptina +  config VIDEO_MT9P031  	tristate "Aptina MT9P031 support"  	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 94f2c99e890d..92773b2e6225 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o  obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o  obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o  obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o +obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o  obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o  obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o  obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o @@ -59,6 +60,7 @@ obj-$(CONFIG_VIDEO_OV7640) += ov7640.o  obj-$(CONFIG_VIDEO_OV7670) += ov7670.o  obj-$(CONFIG_VIDEO_OV9650) += ov9650.o  obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o +obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o  obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o  obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o  obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c new file mode 100644 index 000000000000..beab2f381b81 --- /dev/null +++ b/drivers/media/i2c/ad5820.c @@ -0,0 +1,372 @@ +/* + * drivers/media/i2c/ad5820.c + * + * AD5820 DAC driver for camera voice coil focus. + * + * Copyright (C) 2008 Nokia Corporation + * Copyright (C) 2007 Texas Instruments + * Copyright (C) 2016 Pavel Machek <[email protected]> + * + * Contact: Tuukka Toivonen <[email protected]> + *	    Sakari Ailus <[email protected]> + * + * Based on af_d88.c by Texas Instruments. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +#include <linux/errno.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> + +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-subdev.h> + +#define AD5820_NAME		"ad5820" + +/* Register definitions */ +#define AD5820_POWER_DOWN		(1 << 15) +#define AD5820_DAC_SHIFT		4 +#define AD5820_RAMP_MODE_LINEAR		(0 << 3) +#define AD5820_RAMP_MODE_64_16		(1 << 3) + +#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50) +#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50) + +#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev) + +struct ad5820_device { +	struct v4l2_subdev subdev; +	struct ad5820_platform_data *platform_data; +	struct regulator *vana; + +	struct v4l2_ctrl_handler ctrls; +	u32 focus_absolute; +	u32 focus_ramp_time; +	u32 focus_ramp_mode; + +	struct mutex power_lock; +	int power_count; + +	bool standby; +}; + +static int ad5820_write(struct ad5820_device *coil, u16 data) +{ +	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev); +	struct i2c_msg msg; +	int r; + +	if (!client->adapter) +		return -ENODEV; + +	data = cpu_to_be16(data); +	msg.addr  = client->addr; +	msg.flags = 0; +	msg.len   = 2; +	msg.buf   = (u8 *)&data; + +	r = i2c_transfer(client->adapter, &msg, 1); +	if (r < 0) { +		dev_err(&client->dev, "write failed, error %d\n", r); +		return r; +	} + +	return 0; +} + +/* + * Calculate status word and write it to the device based on current + * values of V4L2 controls. It is assumed that the stored V4L2 control + * values are properly limited and rounded. + */ +static int ad5820_update_hw(struct ad5820_device *coil) +{ +	u16 status; + +	status = RAMP_US_TO_CODE(coil->focus_ramp_time); +	status |= coil->focus_ramp_mode +		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR; +	status |= coil->focus_absolute << AD5820_DAC_SHIFT; + +	if (coil->standby) +		status |= AD5820_POWER_DOWN; + +	return ad5820_write(coil, status); +} + +/* + * Power handling + */ +static int ad5820_power_off(struct ad5820_device *coil, bool standby) +{ +	int ret = 0, ret2; + +	/* +	 * Go to standby first as real power off my be denied by the hardware +	 * (single power line control for both coil and sensor). +	 */ +	if (standby) { +		coil->standby = true; +		ret = ad5820_update_hw(coil); +	} + +	ret2 = regulator_disable(coil->vana); +	if (ret) +		return ret; +	return ret2; +} + +static int ad5820_power_on(struct ad5820_device *coil, bool restore) +{ +	int ret; + +	ret = regulator_enable(coil->vana); +	if (ret < 0) +		return ret; + +	if (restore) { +		/* Restore the hardware settings. */ +		coil->standby = false; +		ret = ad5820_update_hw(coil); +		if (ret) +			goto fail; +	} +	return 0; + +fail: +	coil->standby = true; +	regulator_disable(coil->vana); + +	return ret; +} + +/* + * V4L2 controls + */ +static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl) +{ +	struct ad5820_device *coil = +		container_of(ctrl->handler, struct ad5820_device, ctrls); + +	switch (ctrl->id) { +	case V4L2_CID_FOCUS_ABSOLUTE: +		coil->focus_absolute = ctrl->val; +		return ad5820_update_hw(coil); +	} + +	return 0; +} + +static const struct v4l2_ctrl_ops ad5820_ctrl_ops = { +	.s_ctrl = ad5820_set_ctrl, +}; + + +static int ad5820_init_controls(struct ad5820_device *coil) +{ +	v4l2_ctrl_handler_init(&coil->ctrls, 1); + +	/* +	 * V4L2_CID_FOCUS_ABSOLUTE +	 * +	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is +	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA] +	 * for focus position, because it is meaningless for user. Meaningful +	 * would be to use focus distance or even its inverse, but since the +	 * driver doesn't have sufficiently knowledge to do the conversion, we +	 * will just use abstract codes here. In any case, smaller value = focus +	 * position farther from camera. The default zero value means focus at +	 * infinity, and also least current consumption. +	 */ +	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops, +			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0); + +	if (coil->ctrls.error) +		return coil->ctrls.error; + +	coil->focus_absolute = 0; +	coil->focus_ramp_time = 0; +	coil->focus_ramp_mode = 0; + +	coil->subdev.ctrl_handler = &coil->ctrls; + +	return 0; +} + +/* + * V4L2 subdev operations + */ +static int ad5820_registered(struct v4l2_subdev *subdev) +{ +	struct ad5820_device *coil = to_ad5820_device(subdev); + +	return ad5820_init_controls(coil); +} + +static int +ad5820_set_power(struct v4l2_subdev *subdev, int on) +{ +	struct ad5820_device *coil = to_ad5820_device(subdev); +	int ret = 0; + +	mutex_lock(&coil->power_lock); + +	/* +	 * If the power count is modified from 0 to != 0 or from != 0 to 0, +	 * update the power state. +	 */ +	if (coil->power_count == !on) { +		ret = on ? ad5820_power_on(coil, true) : +			ad5820_power_off(coil, true); +		if (ret < 0) +			goto done; +	} + +	/* Update the power count. */ +	coil->power_count += on ? 1 : -1; +	WARN_ON(coil->power_count < 0); + +done: +	mutex_unlock(&coil->power_lock); +	return ret; +} + +static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ +	return ad5820_set_power(sd, 1); +} + +static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ +	return ad5820_set_power(sd, 0); +} + +static const struct v4l2_subdev_core_ops ad5820_core_ops = { +	.s_power = ad5820_set_power, +}; + +static const struct v4l2_subdev_ops ad5820_ops = { +	.core = &ad5820_core_ops, +}; + +static const struct v4l2_subdev_internal_ops ad5820_internal_ops = { +	.registered = ad5820_registered, +	.open = ad5820_open, +	.close = ad5820_close, +}; + +/* + * I2C driver + */ +static int __maybe_unused ad5820_suspend(struct device *dev) +{ +	struct i2c_client *client = container_of(dev, struct i2c_client, dev); +	struct v4l2_subdev *subdev = i2c_get_clientdata(client); +	struct ad5820_device *coil = to_ad5820_device(subdev); + +	if (!coil->power_count) +		return 0; + +	return ad5820_power_off(coil, false); +} + +static int __maybe_unused ad5820_resume(struct device *dev) +{ +	struct i2c_client *client = container_of(dev, struct i2c_client, dev); +	struct v4l2_subdev *subdev = i2c_get_clientdata(client); +	struct ad5820_device *coil = to_ad5820_device(subdev); + +	if (!coil->power_count) +		return 0; + +	return ad5820_power_on(coil, true); +} + +static int ad5820_probe(struct i2c_client *client, +			const struct i2c_device_id *devid) +{ +	struct ad5820_device *coil; +	int ret; + +	coil = devm_kzalloc(&client->dev, sizeof(*coil), GFP_KERNEL); +	if (!coil) +		return -ENOMEM; + +	coil->vana = devm_regulator_get(&client->dev, "VANA"); +	if (IS_ERR(coil->vana)) { +		ret = PTR_ERR(coil->vana); +		if (ret != -EPROBE_DEFER) +			dev_err(&client->dev, "could not get regulator for vana\n"); +		return ret; +	} + +	mutex_init(&coil->power_lock); + +	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops); +	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; +	coil->subdev.internal_ops = &ad5820_internal_ops; +	strcpy(coil->subdev.name, "ad5820 focus"); + +	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL); +	if (ret < 0) +		goto cleanup2; + +	ret = v4l2_async_register_subdev(&coil->subdev); +	if (ret < 0) +		goto cleanup; + +	return ret; + +cleanup2: +	mutex_destroy(&coil->power_lock); +cleanup: +	media_entity_cleanup(&coil->subdev.entity); +	return ret; +} + +static int __exit ad5820_remove(struct i2c_client *client) +{ +	struct v4l2_subdev *subdev = i2c_get_clientdata(client); +	struct ad5820_device *coil = to_ad5820_device(subdev); + +	v4l2_device_unregister_subdev(&coil->subdev); +	v4l2_ctrl_handler_free(&coil->ctrls); +	media_entity_cleanup(&coil->subdev.entity); +	mutex_destroy(&coil->power_lock); +	return 0; +} + +static const struct i2c_device_id ad5820_id_table[] = { +	{ AD5820_NAME, 0 }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, ad5820_id_table); + +static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume); + +static struct i2c_driver ad5820_i2c_driver = { +	.driver		= { +		.name	= AD5820_NAME, +		.pm	= &ad5820_pm, +	}, +	.probe		= ad5820_probe, +	.remove		= __exit_p(ad5820_remove), +	.id_table	= ad5820_id_table, +}; + +module_i2c_driver(ad5820_i2c_driver); + +MODULE_AUTHOR("Tuukka Toivonen"); +MODULE_DESCRIPTION("AD5820 camera lens driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 0462f461e679..50f354144ee7 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -98,7 +98,6 @@ struct ad9389b_state {  	struct ad9389b_state_edid edid;  	/* Running counter of the number of detected EDIDs (for debugging) */  	unsigned edid_detect_counter; -	struct workqueue_struct *work_queue;  	struct delayed_work edid_handler; /* work entry */  }; @@ -843,8 +842,7 @@ static void ad9389b_edid_handler(struct work_struct *work)  			v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__);  			ad9389b_s_power(sd, false);  			ad9389b_s_power(sd, true); -			queue_delayed_work(state->work_queue, -					   &state->edid_handler, EDID_DELAY); +			schedule_delayed_work(&state->edid_handler, EDID_DELAY);  			return;  		}  	} @@ -933,8 +931,7 @@ static void ad9389b_update_monitor_present_status(struct v4l2_subdev *sd)  		ad9389b_setup(sd);  		ad9389b_notify_monitor_detect(sd);  		state->edid.read_retries = EDID_MAX_RETRIES; -		queue_delayed_work(state->work_queue, -				   &state->edid_handler, EDID_DELAY); +		schedule_delayed_work(&state->edid_handler, EDID_DELAY);  	} else if (!(status & MASK_AD9389B_HPD_DETECT)) {  		v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__);  		state->have_monitor = false; @@ -1065,8 +1062,7 @@ static bool ad9389b_check_edid_status(struct v4l2_subdev *sd)  		ad9389b_wr(sd, 0xc9, 0xf);  		ad9389b_wr(sd, 0xc4, state->edid.segments);  		state->edid.read_retries = EDID_MAX_RETRIES; -		queue_delayed_work(state->work_queue, -				   &state->edid_handler, EDID_DELAY); +		schedule_delayed_work(&state->edid_handler, EDID_DELAY);  		return false;  	} @@ -1170,13 +1166,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id *  		goto err_entity;  	} -	state->work_queue = create_singlethread_workqueue(sd->name); -	if (state->work_queue == NULL) { -		v4l2_err(sd, "could not create workqueue\n"); -		err = -ENOMEM; -		goto err_unreg; -	} -  	INIT_DELAYED_WORK(&state->edid_handler, ad9389b_edid_handler);  	state->dv_timings = dv1080p60; @@ -1187,8 +1176,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id *  		  client->addr << 1, client->adapter->name);  	return 0; -err_unreg: -	i2c_unregister_device(state->edid_i2c_client);  err_entity:  	media_entity_cleanup(&sd->entity);  err_hdl: @@ -1211,9 +1198,8 @@ static int ad9389b_remove(struct i2c_client *client)  	ad9389b_s_stream(sd, false);  	ad9389b_s_audio_stream(sd, false);  	ad9389b_init_setup(sd); -	cancel_delayed_work(&state->edid_handler); +	cancel_delayed_work_sync(&state->edid_handler);  	i2c_unregister_device(state->edid_i2c_client); -	destroy_workqueue(state->work_queue);  	v4l2_device_unregister_subdev(sd);  	media_entity_cleanup(&sd->entity);  	v4l2_ctrl_handler_free(sd->ctrl_handler); @@ -1231,7 +1217,6 @@ MODULE_DEVICE_TABLE(i2c, ad9389b_id);  static struct i2c_driver ad9389b_driver = {  	.driver = { -		.owner = THIS_MODULE,  		.name = "ad9389b",  	},  	.probe = ad9389b_probe, diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 95cbc857f36e..cbed2bc29325 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -26,6 +26,7 @@  #include <linux/i2c.h>  #include <linux/slab.h>  #include <linux/of.h> +#include <linux/gpio/consumer.h>  #include <linux/videodev2.h>  #include <media/v4l2-ioctl.h>  #include <media/v4l2-event.h> @@ -56,10 +57,11 @@  #define ADV7182_REG_INPUT_VIDSEL			0x0002 +#define ADV7180_REG_OUTPUT_CONTROL			0x0003  #define ADV7180_REG_EXTENDED_OUTPUT_CONTROL		0x0004  #define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS		0xC5 -#define ADV7180_REG_AUTODETECT_ENABLE			0x07 +#define ADV7180_REG_AUTODETECT_ENABLE			0x0007  #define ADV7180_AUTODETECT_DEFAULT			0x7f  /* Contrast */  #define ADV7180_REG_CON		0x0008	/*Unsigned */ @@ -100,6 +102,20 @@  #define ADV7180_REG_IDENT 0x0011  #define ADV7180_ID_7180 0x18 +#define ADV7180_REG_STATUS3		0x0013 +#define ADV7180_REG_ANALOG_CLAMP_CTL	0x0014 +#define ADV7180_REG_SHAP_FILTER_CTL_1	0x0017 +#define ADV7180_REG_CTRL_2		0x001d +#define ADV7180_REG_VSYNC_FIELD_CTL_1	0x0031 +#define ADV7180_REG_MANUAL_WIN_CTL_1	0x003d +#define ADV7180_REG_MANUAL_WIN_CTL_2	0x003e +#define ADV7180_REG_MANUAL_WIN_CTL_3	0x003f +#define ADV7180_REG_LOCK_CNT		0x0051 +#define ADV7180_REG_CVBS_TRIM		0x0052 +#define ADV7180_REG_CLAMP_ADJ		0x005a +#define ADV7180_REG_RES_CIR		0x005f +#define ADV7180_REG_DIFF_MODE		0x0060 +  #define ADV7180_REG_ICONF1		0x2040  #define ADV7180_ICONF1_ACTIVE_LOW	0x01  #define ADV7180_ICONF1_PSYNC_ONLY	0x10 @@ -129,9 +145,15 @@  #define ADV7180_REG_VPP_SLAVE_ADDR	0xFD  #define ADV7180_REG_CSI_SLAVE_ADDR	0xFE -#define ADV7180_REG_FLCONTROL 0x40e0 +#define ADV7180_REG_ACE_CTRL1		0x4080 +#define ADV7180_REG_ACE_CTRL5		0x4084 +#define ADV7180_REG_FLCONTROL		0x40e0  #define ADV7180_FLCONTROL_FL_ENABLE 0x1 +#define ADV7180_REG_RST_CLAMP	0x809c +#define ADV7180_REG_AGC_ADJ1	0x80b6 +#define ADV7180_REG_AGC_ADJ2	0x80c0 +  #define ADV7180_CSI_REG_PWRDN	0x00  #define ADV7180_CSI_PWRDN	0x80 @@ -192,6 +214,7 @@ struct adv7180_state {  	struct media_pad	pad;  	struct mutex		mutex; /* mutual excl. when accessing chip */  	int			irq; +	struct gpio_desc	*pwdn_gpio;  	v4l2_std_id		curr_norm;  	bool			powered;  	bool			streaming; @@ -442,6 +465,19 @@ static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)  	return 0;  } +static void adv7180_set_power_pin(struct adv7180_state *state, bool on) +{ +	if (!state->pwdn_gpio) +		return; + +	if (on) { +		gpiod_set_value_cansleep(state->pwdn_gpio, 0); +		usleep_range(5000, 10000); +	} else { +		gpiod_set_value_cansleep(state->pwdn_gpio, 1); +	} +} +  static int adv7180_set_power(struct adv7180_state *state, bool on)  {  	u8 val; @@ -597,7 +633,7 @@ static int adv7180_enum_mbus_code(struct v4l2_subdev *sd,  	if (code->index != 0)  		return -EINVAL; -	code->code = MEDIA_BUS_FMT_YUYV8_2X8; +	code->code = MEDIA_BUS_FMT_UYVY8_2X8;  	return 0;  } @@ -607,7 +643,7 @@ static int adv7180_mbus_fmt(struct v4l2_subdev *sd,  {  	struct adv7180_state *state = to_state(sd); -	fmt->code = MEDIA_BUS_FMT_YUYV8_2X8; +	fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;  	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;  	fmt->width = 720;  	fmt->height = state->curr_norm & V4L2_STD_525_60 ? 480 : 576; @@ -675,6 +711,7 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd,  {  	struct adv7180_state *state = to_state(sd);  	struct v4l2_mbus_framefmt *framefmt; +	int ret;  	switch (format->format.field) {  	case V4L2_FIELD_NONE: @@ -686,8 +723,9 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd,  		break;  	} +	ret = adv7180_mbus_fmt(sd,  &format->format); +  	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { -		framefmt = &format->format;  		if (state->field != format->format.field) {  			state->field = format->format.field;  			adv7180_set_power(state, false); @@ -699,7 +737,7 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd,  		*framefmt = format->format;  	} -	return adv7180_mbus_fmt(sd, framefmt); +	return ret;  }  static int adv7180_g_mbus_config(struct v4l2_subdev *sd, @@ -725,16 +763,16 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd,  	return 0;  } -static int adv7180_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cropcap) +static int adv7180_g_pixelaspect(struct v4l2_subdev *sd, struct v4l2_fract *aspect)  {  	struct adv7180_state *state = to_state(sd);  	if (state->curr_norm & V4L2_STD_525_60) { -		cropcap->pixelaspect.numerator = 11; -		cropcap->pixelaspect.denominator = 10; +		aspect->numerator = 11; +		aspect->denominator = 10;  	} else { -		cropcap->pixelaspect.numerator = 54; -		cropcap->pixelaspect.denominator = 59; +		aspect->numerator = 54; +		aspect->denominator = 59;  	}  	return 0; @@ -787,7 +825,7 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = {  	.g_input_status = adv7180_g_input_status,  	.s_routing = adv7180_s_routing,  	.g_mbus_config = adv7180_g_mbus_config, -	.cropcap = adv7180_cropcap, +	.g_pixelaspect = adv7180_g_pixelaspect,  	.g_tvnorms = adv7180_g_tvnorms,  	.s_stream = adv7180_s_stream,  }; @@ -886,16 +924,20 @@ static int adv7182_init(struct adv7180_state *state)  	/* ADI required writes */  	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { -		adv7180_write(state, 0x0003, 0x4e); -		adv7180_write(state, 0x0004, 0x57); -		adv7180_write(state, 0x001d, 0xc0); +		adv7180_write(state, ADV7180_REG_OUTPUT_CONTROL, 0x4e); +		adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x57); +		adv7180_write(state, ADV7180_REG_CTRL_2, 0xc0);  	} else {  		if (state->chip_info->flags & ADV7180_FLAG_V2) -			adv7180_write(state, 0x0004, 0x17); +			adv7180_write(state, +				      ADV7180_REG_EXTENDED_OUTPUT_CONTROL, +				      0x17);  		else -			adv7180_write(state, 0x0004, 0x07); -		adv7180_write(state, 0x0003, 0x0c); -		adv7180_write(state, 0x001d, 0x40); +			adv7180_write(state, +				      ADV7180_REG_EXTENDED_OUTPUT_CONTROL, +				      0x07); +		adv7180_write(state, ADV7180_REG_OUTPUT_CONTROL, 0x0c); +		adv7180_write(state, ADV7180_REG_CTRL_2, 0x40);  	}  	adv7180_write(state, 0x0013, 0x00); @@ -972,8 +1014,8 @@ static int adv7182_select_input(struct adv7180_state *state, unsigned int input)  		return ret;  	/* Reset clamp circuitry - ADI recommended writes */ -	adv7180_write(state, 0x809c, 0x00); -	adv7180_write(state, 0x809c, 0xff); +	adv7180_write(state, ADV7180_REG_RST_CLAMP, 0x00); +	adv7180_write(state, ADV7180_REG_RST_CLAMP, 0xff);  	input_type = adv7182_get_input_type(input); @@ -981,10 +1023,10 @@ static int adv7182_select_input(struct adv7180_state *state, unsigned int input)  	case ADV7182_INPUT_TYPE_CVBS:  	case ADV7182_INPUT_TYPE_DIFF_CVBS:  		/* ADI recommends to use the SH1 filter */ -		adv7180_write(state, 0x0017, 0x41); +		adv7180_write(state, ADV7180_REG_SHAP_FILTER_CTL_1, 0x41);  		break;  	default: -		adv7180_write(state, 0x0017, 0x01); +		adv7180_write(state, ADV7180_REG_SHAP_FILTER_CTL_1, 0x01);  		break;  	} @@ -994,21 +1036,21 @@ static int adv7182_select_input(struct adv7180_state *state, unsigned int input)  		lbias = adv7182_lbias_settings[input_type];  	for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++) -		adv7180_write(state, 0x0052 + i, lbias[i]); +		adv7180_write(state, ADV7180_REG_CVBS_TRIM + i, lbias[i]);  	if (input_type == ADV7182_INPUT_TYPE_DIFF_CVBS) {  		/* ADI required writes to make differential CVBS work */ -		adv7180_write(state, 0x005f, 0xa8); -		adv7180_write(state, 0x005a, 0x90); -		adv7180_write(state, 0x0060, 0xb0); -		adv7180_write(state, 0x80b6, 0x08); -		adv7180_write(state, 0x80c0, 0xa0); +		adv7180_write(state, ADV7180_REG_RES_CIR, 0xa8); +		adv7180_write(state, ADV7180_REG_CLAMP_ADJ, 0x90); +		adv7180_write(state, ADV7180_REG_DIFF_MODE, 0xb0); +		adv7180_write(state, ADV7180_REG_AGC_ADJ1, 0x08); +		adv7180_write(state, ADV7180_REG_AGC_ADJ2, 0xa0);  	} else { -		adv7180_write(state, 0x005f, 0xf0); -		adv7180_write(state, 0x005a, 0xd0); -		adv7180_write(state, 0x0060, 0x10); -		adv7180_write(state, 0x80b6, 0x9c); -		adv7180_write(state, 0x80c0, 0x00); +		adv7180_write(state, ADV7180_REG_RES_CIR, 0xf0); +		adv7180_write(state, ADV7180_REG_CLAMP_ADJ, 0xd0); +		adv7180_write(state, ADV7180_REG_DIFF_MODE, 0x10); +		adv7180_write(state, ADV7180_REG_AGC_ADJ1, 0x9c); +		adv7180_write(state, ADV7180_REG_AGC_ADJ2, 0x00);  	}  	return 0; @@ -1185,6 +1227,8 @@ static int init_device(struct adv7180_state *state)  	mutex_lock(&state->mutex); +	adv7180_set_power_pin(state, true); +  	adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES);  	usleep_range(5000, 10000); @@ -1254,6 +1298,14 @@ static int adv7180_probe(struct i2c_client *client,  	state->field = V4L2_FIELD_INTERLACED;  	state->chip_info = (struct adv7180_chip_info *)id->driver_data; +	state->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown", +						   GPIOD_OUT_HIGH); +	if (IS_ERR(state->pwdn_gpio)) { +		ret = PTR_ERR(state->pwdn_gpio); +		v4l_err(client, "request for power pin failed: %d\n", ret); +		return ret; +	} +  	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {  		state->csi_client = i2c_new_dummy(client->adapter,  				ADV7180_DEFAULT_CSI_I2C_ADDR); @@ -1345,6 +1397,8 @@ static int adv7180_remove(struct i2c_client *client)  	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)  		i2c_unregister_device(state->csi_client); +	adv7180_set_power_pin(state, false); +  	mutex_destroy(&state->mutex);  	return 0; diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 2bec737881e9..04eecda74d66 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -644,7 +644,6 @@ MODULE_DEVICE_TABLE(i2c, adv7183_id);  static struct i2c_driver adv7183_driver = {  	.driver = { -		.owner  = THIS_MODULE,  		.name   = "adv7183",  	},  	.probe          = adv7183_probe, diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c index 76d987476e35..f19ad4ecd11e 100644 --- a/drivers/media/i2c/adv7393.c +++ b/drivers/media/i2c/adv7393.c @@ -456,7 +456,6 @@ MODULE_DEVICE_TABLE(i2c, adv7393_id);  static struct i2c_driver adv7393_driver = {  	.driver = { -		.owner	= THIS_MODULE,  		.name	= "adv7393",  	},  	.probe		= adv7393_probe, diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 53030d631653..5ba0f21bcfe4 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -1898,6 +1898,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *  					       state->i2c_cec_addr >> 1);  		if (state->i2c_cec == NULL) {  			v4l2_err(sd, "failed to register cec i2c client\n"); +			err = -ENOMEM;  			goto err_unreg_edid;  		}  		adv7511_wr(sd, 0xe2, 0x00); /* power up cec section */ diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index d9f2b6b76d59..3a795dcb7d8e 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -124,21 +124,27 @@ static int ak881x_enum_mbus_code(struct v4l2_subdev *sd,  	return 0;  } -static int ak881x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +static int ak881x_get_selection(struct v4l2_subdev *sd, +				struct v4l2_subdev_pad_config *cfg, +				struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct ak881x *ak881x = to_ak881x(client); -	a->bounds.left			= 0; -	a->bounds.top			= 0; -	a->bounds.width			= 720; -	a->bounds.height		= ak881x->lines; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_OUTPUT; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = 0; +		sel->r.top = 0; +		sel->r.width = 720; +		sel->r.height = ak881x->lines; +		return 0; +	default: +		return -EINVAL; +	}  }  static int ak881x_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) @@ -207,13 +213,13 @@ static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = {  };  static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = { -	.cropcap	= ak881x_cropcap,  	.s_std_output	= ak881x_s_std_output,  	.s_stream	= ak881x_s_stream,  };  static const struct v4l2_subdev_pad_ops ak881x_subdev_pad_ops = {  	.enum_mbus_code = ak881x_enum_mbus_code, +	.get_selection	= ak881x_get_selection,  	.set_fmt	= ak881x_fill_fmt,  	.get_fmt	= ak881x_fill_fmt,  }; diff --git a/drivers/media/i2c/cs3308.c b/drivers/media/i2c/cs3308.c index d28b4f37fe5f..7da5f69cace6 100644 --- a/drivers/media/i2c/cs3308.c +++ b/drivers/media/i2c/cs3308.c @@ -127,7 +127,6 @@ MODULE_DEVICE_TABLE(i2c, cs3308_id);  static struct i2c_driver cs3308_driver = {  	.driver = { -		.owner  = THIS_MODULE,  		.name   = "cs3308",  	},  	.probe          = cs3308_probe, diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index bf82726fd3f4..f95a6bc839d5 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -35,6 +35,7 @@   *   */ +#include <asm/unaligned.h>  #include <linux/module.h>  #include <linux/init.h>  #include <linux/kernel.h> @@ -63,51 +64,80 @@ module_param(debug, int, 0644);    /* debug level (0,1,2) */  /* ----------------------------------------------------------------------- */  static int get_key_haup_common(struct IR_i2c *ir, enum rc_type *protocol, -			       u32 *scancode, u8 *ptoggle, int size, int offset) +					u32 *scancode, u8 *ptoggle, int size)  {  	unsigned char buf[6]; -	int start, range, toggle, dev, code, ircode; +	int start, range, toggle, dev, code, ircode, vendor;  	/* poll IR chip */  	if (size != i2c_master_recv(ir->c, buf, size))  		return -EIO; -	/* split rc5 data block ... */ -	start  = (buf[offset] >> 7) &    1; -	range  = (buf[offset] >> 6) &    1; -	toggle = (buf[offset] >> 5) &    1; -	dev    =  buf[offset]       & 0x1f; -	code   = (buf[offset+1] >> 2) & 0x3f; +	if (buf[0] & 0x80) { +		int offset = (size == 6) ? 3 : 0; -	/* rc5 has two start bits -	 * the first bit must be one -	 * the second bit defines the command range (1 = 0-63, 0 = 64 - 127) -	 */ -	if (!start) -		/* no key pressed */ -		return 0; +		/* split rc5 data block ... */ +		start  = (buf[offset] >> 7) &    1; +		range  = (buf[offset] >> 6) &    1; +		toggle = (buf[offset] >> 5) &    1; +		dev    =  buf[offset]       & 0x1f; +		code   = (buf[offset+1] >> 2) & 0x3f; -	/* filter out invalid key presses */ -	ircode = (start << 12) | (toggle << 11) | (dev << 6) | code; -	if ((ircode & 0x1fff) == 0x1fff) -		return 0; +		/* rc5 has two start bits +		 * the first bit must be one +		 * the second bit defines the command range: +		 * 1 = 0-63, 0 = 64 - 127 +		 */ +		if (!start) +			/* no key pressed */ +			return 0; -	if (!range) -		code += 64; +		/* filter out invalid key presses */ +		ircode = (start << 12) | (toggle << 11) | (dev << 6) | code; +		if ((ircode & 0x1fff) == 0x1fff) +			return 0; -	dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n", -		start, range, toggle, dev, code); +		if (!range) +			code += 64; -	*protocol = RC_TYPE_RC5; -	*scancode = RC_SCANCODE_RC5(dev, code); -	*ptoggle = toggle; -	return 1; +		dprintk(1, "ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n", +			start, range, toggle, dev, code); + +		*protocol = RC_TYPE_RC5; +		*scancode = RC_SCANCODE_RC5(dev, code); +		*ptoggle = toggle; + +		return 1; +	} else if (size == 6 && (buf[0] & 0x40)) { +		code = buf[4]; +		dev = buf[3]; +		vendor = get_unaligned_be16(buf + 1); + +		if (vendor == 0x800f) { +			*ptoggle = (dev & 0x80) != 0; +			*protocol = RC_TYPE_RC6_MCE; +			dev &= 0x7f; +			dprintk(1, "ir hauppauge (rc6-mce): t%d vendor=%d dev=%d code=%d\n", +						toggle, vendor, dev, code); +		} else { +			*ptoggle = 0; +			*protocol = RC_TYPE_RC6_6A_32; +			dprintk(1, "ir hauppauge (rc6-6a-32): vendor=%d dev=%d code=%d\n", +							vendor, dev, code); +		} + +		*scancode = RC_SCANCODE_RC6_6A(vendor, dev, code); + +		return 1; +	} + +	return 0;  }  static int get_key_haup(struct IR_i2c *ir, enum rc_type *protocol,  			u32 *scancode, u8 *toggle)  { -	return get_key_haup_common (ir, protocol, scancode, toggle, 3, 0); +	return get_key_haup_common(ir, protocol, scancode, toggle, 3);  }  static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_type *protocol, @@ -126,7 +156,7 @@ static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_type *protocol,  	if (ret != 1)  		return (ret < 0) ? ret : -EINVAL; -	return get_key_haup_common(ir, protocol, scancode, toggle, 6, 3); +	return get_key_haup_common(ir, protocol, scancode, toggle, 6);  }  static int get_key_pixelview(struct IR_i2c *ir, enum rc_type *protocol, @@ -347,7 +377,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)  	case 0x71:  		name        = "Hauppauge/Zilog Z8";  		ir->get_key = get_key_haup_xvr; -		rc_type     = RC_BIT_RC5; +		rc_type     = RC_BIT_RC5 | RC_BIT_RC6_MCE | RC_BIT_RC6_6A_32;  		ir_codes    = RC_MAP_HAUPPAUGE;  		break;  	} diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/mt9m111.c index 6dfaead6aaa8..72e71b762827 100644 --- a/drivers/media/i2c/soc_camera/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -16,10 +16,11 @@  #include <linux/v4l2-mediabus.h>  #include <linux/module.h> -#include <media/soc_camera.h> +#include <media/v4l2-async.h>  #include <media/v4l2-clk.h>  #include <media/v4l2-common.h>  #include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h>  /*   * MT9M111, MT9M112 and MT9M131: @@ -187,10 +188,10 @@ struct mt9m111_datafmt {  };  static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { -	{MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}, -	{MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG}, -	{MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG}, -	{MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG}, +	{MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB}, +	{MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_SRGB}, +	{MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB}, +	{MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_SRGB},  	{MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},  	{MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},  	{MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, @@ -383,30 +384,36 @@ static int mt9m111_reset(struct mt9m111 *mt9m111)  	return ret;  } -static int mt9m111_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int mt9m111_set_selection(struct v4l2_subdev *sd, +				 struct v4l2_subdev_pad_config *cfg, +				 struct v4l2_subdev_selection *sel)  { -	struct v4l2_rect rect = a->c; -	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); +	struct i2c_client *client = v4l2_get_subdevdata(sd); +	struct mt9m111 *mt9m111 = to_mt9m111(client); +	struct v4l2_rect rect = sel->r;  	int width, height; -	int ret; +	int ret, align = 0; -	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP)  		return -EINVAL;  	if (mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||  	    mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {  		/* Bayer format - even size lengths */ -		rect.width	= ALIGN(rect.width, 2); -		rect.height	= ALIGN(rect.height, 2); +		align = 1;  		/* Let the user play with the starting pixel */  	}  	/* FIXME: the datasheet doesn't specify minimum sizes */ -	soc_camera_limit_side(&rect.left, &rect.width, -		     MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH); - -	soc_camera_limit_side(&rect.top, &rect.height, -		     MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT); +	v4l_bound_align_image(&rect.width, 2, MT9M111_MAX_WIDTH, align, +			      &rect.height, 2, MT9M111_MAX_HEIGHT, align, 0); +	rect.left = clamp(rect.left, MT9M111_MIN_DARK_COLS, +			  MT9M111_MIN_DARK_COLS + MT9M111_MAX_WIDTH - +			  (__s32)rect.width); +	rect.top = clamp(rect.top, MT9M111_MIN_DARK_ROWS, +			 MT9M111_MIN_DARK_ROWS + MT9M111_MAX_HEIGHT - +			 (__s32)rect.height);  	width = min(mt9m111->width, rect.width);  	height = min(mt9m111->height, rect.height); @@ -421,30 +428,30 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)  	return ret;  } -static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9m111_get_selection(struct v4l2_subdev *sd, +				 struct v4l2_subdev_pad_config *cfg, +				 struct v4l2_subdev_selection *sel)  { -	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); - -	a->c	= mt9m111->rect; -	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} +	struct i2c_client *client = v4l2_get_subdevdata(sd); +	struct mt9m111 *mt9m111 = to_mt9m111(client); -static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)  		return -EINVAL; -	a->bounds.left			= MT9M111_MIN_DARK_COLS; -	a->bounds.top			= MT9M111_MIN_DARK_ROWS; -	a->bounds.width			= MT9M111_MAX_WIDTH; -	a->bounds.height		= MT9M111_MAX_HEIGHT; -	a->defrect			= a->bounds; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; - -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = MT9M111_MIN_DARK_COLS; +		sel->r.top = MT9M111_MIN_DARK_ROWS; +		sel->r.width = MT9M111_MAX_WIDTH; +		sel->r.height = MT9M111_MAX_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = mt9m111->rect; +		return 0; +	default: +		return -EINVAL; +	}  }  static int mt9m111_get_fmt(struct v4l2_subdev *sd, @@ -775,17 +782,16 @@ static int mt9m111_init(struct mt9m111 *mt9m111)  static int mt9m111_power_on(struct mt9m111 *mt9m111)  {  	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); -	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);  	int ret; -	ret = soc_camera_power_on(&client->dev, ssdd, mt9m111->clk); +	ret = v4l2_clk_enable(mt9m111->clk);  	if (ret < 0)  		return ret;  	ret = mt9m111_resume(mt9m111);  	if (ret < 0) {  		dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret); -		soc_camera_power_off(&client->dev, ssdd, mt9m111->clk); +		v4l2_clk_disable(mt9m111->clk);  	}  	return ret; @@ -793,11 +799,8 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111)  static void mt9m111_power_off(struct mt9m111 *mt9m111)  { -	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); -	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); -  	mt9m111_suspend(mt9m111); -	soc_camera_power_off(&client->dev, ssdd, mt9m111->clk); +	v4l2_clk_disable(mt9m111->clk);  }  static int mt9m111_s_power(struct v4l2_subdev *sd, int on) @@ -854,27 +857,22 @@ static int mt9m111_enum_mbus_code(struct v4l2_subdev *sd,  static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,  				struct v4l2_mbus_config *cfg)  { -	struct i2c_client *client = v4l2_get_subdevdata(sd); -	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); -  	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |  		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |  		V4L2_MBUS_DATA_ACTIVE_HIGH;  	cfg->type = V4L2_MBUS_PARALLEL; -	cfg->flags = soc_camera_apply_board_flags(ssdd, cfg);  	return 0;  }  static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { -	.s_crop		= mt9m111_s_crop, -	.g_crop		= mt9m111_g_crop, -	.cropcap	= mt9m111_cropcap,  	.g_mbus_config	= mt9m111_g_mbus_config,  };  static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = {  	.enum_mbus_code = mt9m111_enum_mbus_code, +	.get_selection	= mt9m111_get_selection, +	.set_selection	= mt9m111_set_selection,  	.get_fmt	= mt9m111_get_fmt,  	.set_fmt	= mt9m111_set_fmt,  }; @@ -933,20 +931,8 @@ static int mt9m111_probe(struct i2c_client *client,  {  	struct mt9m111 *mt9m111;  	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); -	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);  	int ret; -	if (client->dev.of_node) { -		ssdd = devm_kzalloc(&client->dev, sizeof(*ssdd), GFP_KERNEL); -		if (!ssdd) -			return -ENOMEM; -		client->dev.platform_data = ssdd; -	} -	if (!ssdd) { -		dev_err(&client->dev, "mt9m111: driver needs platform data\n"); -		return -EINVAL; -	} -  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {  		dev_warn(&adapter->dev,  			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); @@ -992,10 +978,6 @@ static int mt9m111_probe(struct i2c_client *client,  	mt9m111->lastpage	= -1;  	mutex_init(&mt9m111->power_lock); -	ret = soc_camera_power_init(&client->dev, ssdd); -	if (ret < 0) -		goto out_hdlfree; -  	ret = mt9m111_video_probe(client);  	if (ret < 0)  		goto out_hdlfree; diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index be5a7fd4f076..502c72238a4a 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -23,6 +23,7 @@  #include <linux/videodev2.h>  #include <media/media-entity.h> +#include <media/v4l2-async.h>  #include <media/v4l2-ctrls.h>  #include <media/v4l2-device.h>  #include <media/v4l2-event.h> @@ -1520,6 +1521,10 @@ static int ov965x_probe(struct i2c_client *client,  	/* Update exposure time min/max to match frame format */  	ov965x_update_exposure_ctrl(ov965x); +	ret = v4l2_async_register_subdev(sd); +	if (ret < 0) +		goto err_ctrls; +  	return 0;  err_ctrls:  	v4l2_ctrl_handler_free(sd->ctrl_handler); @@ -1532,7 +1537,7 @@ static int ov965x_remove(struct i2c_client *client)  {  	struct v4l2_subdev *sd = i2c_get_clientdata(client); -	v4l2_device_unregister_subdev(sd); +	v4l2_async_unregister_subdev(sd);  	v4l2_ctrl_handler_free(sd->ctrl_handler);  	media_entity_cleanup(&sd->entity); diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 08af58fb8e7d..3844853ab0a0 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1706,7 +1706,7 @@ static int s5c73m3_probe(struct i2c_client *client,  	state->oif_pads[OIF_ISP_PAD].flags = MEDIA_PAD_FL_SINK;  	state->oif_pads[OIF_JPEG_PAD].flags = MEDIA_PAD_FL_SINK;  	state->oif_pads[OIF_SOURCE_PAD].flags = MEDIA_PAD_FL_SOURCE; -	oif_sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; +	oif_sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;  	ret = media_entity_pads_init(&oif_sd->entity, OIF_NUM_PADS,  							state->oif_pads); diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c index 8a0f22da590f..6ebcf254989a 100644 --- a/drivers/media/i2c/s5k4ecgx.c +++ b/drivers/media/i2c/s5k4ecgx.c @@ -1019,7 +1019,6 @@ MODULE_DEVICE_TABLE(i2c, s5k4ecgx_id);  static struct i2c_driver v4l2_i2c_driver = {  	.driver = { -		.owner	= THIS_MODULE,  		.name = S5K4ECGX_DRIVER_NAME,  	},  	.probe = s5k4ecgx_probe, diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index cbe4711e9b31..769964057881 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -331,6 +331,7 @@ static int s5k6a3_probe(struct i2c_client *client,  	sensor->format.width = S5K6A3_DEFAULT_WIDTH;  	sensor->format.height = S5K6A3_DEFAULT_HEIGHT; +	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;  	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;  	ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad);  	if (ret < 0) @@ -376,7 +377,6 @@ static struct i2c_driver s5k6a3_driver = {  	.driver = {  		.of_match_table	= of_match_ptr(s5k6a3_of_match),  		.name		= S5K6A3_DRV_NAME, -		.owner		= THIS_MODULE,  	},  	.probe		= s5k6a3_probe,  	.remove		= s5k6a3_remove, diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index d08ab6c8357c..44f8c7e10a35 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -24,8 +24,8 @@  #include <linux/delay.h>  #include <linux/device.h>  #include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/module.h> -#include <linux/of_gpio.h>  #include <linux/regulator/consumer.h>  #include <linux/slab.h>  #include <linux/smiapp.h> @@ -328,6 +328,14 @@ static void __smiapp_update_exposure_limits(struct smiapp_sensor *sensor)   *    orders must be defined.   */  static const struct smiapp_csi_data_format smiapp_csi_data_formats[] = { +	{ MEDIA_BUS_FMT_SGRBG16_1X16, 16, 16, SMIAPP_PIXEL_ORDER_GRBG, }, +	{ MEDIA_BUS_FMT_SRGGB16_1X16, 16, 16, SMIAPP_PIXEL_ORDER_RGGB, }, +	{ MEDIA_BUS_FMT_SBGGR16_1X16, 16, 16, SMIAPP_PIXEL_ORDER_BGGR, }, +	{ MEDIA_BUS_FMT_SGBRG16_1X16, 16, 16, SMIAPP_PIXEL_ORDER_GBRG, }, +	{ MEDIA_BUS_FMT_SGRBG14_1X14, 14, 14, SMIAPP_PIXEL_ORDER_GRBG, }, +	{ MEDIA_BUS_FMT_SRGGB14_1X14, 14, 14, SMIAPP_PIXEL_ORDER_RGGB, }, +	{ MEDIA_BUS_FMT_SBGGR14_1X14, 14, 14, SMIAPP_PIXEL_ORDER_BGGR, }, +	{ MEDIA_BUS_FMT_SGBRG14_1X14, 14, 14, SMIAPP_PIXEL_ORDER_GBRG, },  	{ MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GRBG, },  	{ MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_RGGB, },  	{ MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_BGGR, }, @@ -625,12 +633,12 @@ static int smiapp_init_late_controls(struct smiapp_sensor *sensor)  				0, max_value, 1, max_value);  	} -	for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++); +	for (max = 0; sensor->hwcfg->op_sys_clock[max + 1]; max++);  	sensor->link_freq = v4l2_ctrl_new_int_menu(  		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,  		V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs), -		__ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock); +		__ffs(*valid_link_freqs), sensor->hwcfg->op_sys_clock);  	return sensor->src->ctrl_handler.error;  } @@ -833,8 +841,8 @@ static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor)  		pll->bits_per_pixel = f->compressed; -		for (j = 0; sensor->platform_data->op_sys_clock[j]; j++) { -			pll->link_freq = sensor->platform_data->op_sys_clock[j]; +		for (j = 0; sensor->hwcfg->op_sys_clock[j]; j++) { +			pll->link_freq = sensor->hwcfg->op_sys_clock[j];  			rval = smiapp_pll_try(sensor, pll);  			dev_dbg(&client->dev, "link freq %u Hz, bpp %u %s\n", @@ -1032,22 +1040,22 @@ static int smiapp_change_cci_addr(struct smiapp_sensor *sensor)  	int rval;  	u32 val; -	client->addr = sensor->platform_data->i2c_addr_dfl; +	client->addr = sensor->hwcfg->i2c_addr_dfl;  	rval = smiapp_write(sensor,  			    SMIAPP_REG_U8_CCI_ADDRESS_CONTROL, -			    sensor->platform_data->i2c_addr_alt << 1); +			    sensor->hwcfg->i2c_addr_alt << 1);  	if (rval)  		return rval; -	client->addr = sensor->platform_data->i2c_addr_alt; +	client->addr = sensor->hwcfg->i2c_addr_alt;  	/* verify addr change went ok */  	rval = smiapp_read(sensor, SMIAPP_REG_U8_CCI_ADDRESS_CONTROL, &val);  	if (rval)  		return rval; -	if (val != sensor->platform_data->i2c_addr_alt << 1) +	if (val != sensor->hwcfg->i2c_addr_alt << 1)  		return -ENODEV;  	return 0; @@ -1061,13 +1069,13 @@ static int smiapp_change_cci_addr(struct smiapp_sensor *sensor)  static int smiapp_setup_flash_strobe(struct smiapp_sensor *sensor)  {  	struct smiapp_flash_strobe_parms *strobe_setup; -	unsigned int ext_freq = sensor->platform_data->ext_clk; +	unsigned int ext_freq = sensor->hwcfg->ext_clk;  	u32 tmp;  	u32 strobe_adjustment;  	u32 strobe_width_high_rs;  	int rval; -	strobe_setup = sensor->platform_data->strobe_setup; +	strobe_setup = sensor->hwcfg->strobe_setup;  	/*  	 * How to calculate registers related to strobe length. Please @@ -1179,7 +1187,7 @@ static int smiapp_setup_flash_strobe(struct smiapp_sensor *sensor)  			    strobe_setup->trigger);  out: -	sensor->platform_data->strobe_setup->trigger = 0; +	sensor->hwcfg->strobe_setup->trigger = 0;  	return rval;  } @@ -1201,21 +1209,16 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)  	}  	usleep_range(1000, 1000); -	if (sensor->platform_data->set_xclk) -		rval = sensor->platform_data->set_xclk( -			&sensor->src->sd, sensor->platform_data->ext_clk); -	else -		rval = clk_prepare_enable(sensor->ext_clk); +	rval = clk_prepare_enable(sensor->ext_clk);  	if (rval < 0) {  		dev_dbg(&client->dev, "failed to enable xclk\n");  		goto out_xclk_fail;  	}  	usleep_range(1000, 1000); -	if (gpio_is_valid(sensor->platform_data->xshutdown)) -		gpio_set_value(sensor->platform_data->xshutdown, 1); +	gpiod_set_value(sensor->xshutdown, 1); -	sleep = SMIAPP_RESET_DELAY(sensor->platform_data->ext_clk); +	sleep = SMIAPP_RESET_DELAY(sensor->hwcfg->ext_clk);  	usleep_range(sleep, sleep);  	/* @@ -1229,7 +1232,7 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)  	 * is found.  	 */ -	if (sensor->platform_data->i2c_addr_alt) { +	if (sensor->hwcfg->i2c_addr_alt) {  		rval = smiapp_change_cci_addr(sensor);  		if (rval) {  			dev_err(&client->dev, "cci address change error\n"); @@ -1244,7 +1247,7 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)  		goto out_cci_addr_fail;  	} -	if (sensor->platform_data->i2c_addr_alt) { +	if (sensor->hwcfg->i2c_addr_alt) {  		rval = smiapp_change_cci_addr(sensor);  		if (rval) {  			dev_err(&client->dev, "cci address change error\n"); @@ -1261,14 +1264,14 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)  	rval = smiapp_write(  		sensor, SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ, -		sensor->platform_data->ext_clk / (1000000 / (1 << 8))); +		sensor->hwcfg->ext_clk / (1000000 / (1 << 8)));  	if (rval) {  		dev_err(&client->dev, "extclk frequency set failed\n");  		goto out_cci_addr_fail;  	}  	rval = smiapp_write(sensor, SMIAPP_REG_U8_CSI_LANE_MODE, -			    sensor->platform_data->lanes - 1); +			    sensor->hwcfg->lanes - 1);  	if (rval) {  		dev_err(&client->dev, "csi lane mode set failed\n");  		goto out_cci_addr_fail; @@ -1282,7 +1285,7 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)  	}  	rval = smiapp_write(sensor, SMIAPP_REG_U8_CSI_SIGNALLING_MODE, -			    sensor->platform_data->csi_signalling_mode); +			    sensor->hwcfg->csi_signalling_mode);  	if (rval) {  		dev_err(&client->dev, "csi signalling mode set failed\n");  		goto out_cci_addr_fail; @@ -1322,12 +1325,8 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)  	return 0;  out_cci_addr_fail: -	if (gpio_is_valid(sensor->platform_data->xshutdown)) -		gpio_set_value(sensor->platform_data->xshutdown, 0); -	if (sensor->platform_data->set_xclk) -		sensor->platform_data->set_xclk(&sensor->src->sd, 0); -	else -		clk_disable_unprepare(sensor->ext_clk); +	gpiod_set_value(sensor->xshutdown, 0); +	clk_disable_unprepare(sensor->ext_clk);  out_xclk_fail:  	regulator_disable(sensor->vana); @@ -1343,17 +1342,13 @@ static void smiapp_power_off(struct smiapp_sensor *sensor)  	 * really see a power off and next time the cci address change  	 * will fail. So do a soft reset explicitly here.  	 */ -	if (sensor->platform_data->i2c_addr_alt) +	if (sensor->hwcfg->i2c_addr_alt)  		smiapp_write(sensor,  			     SMIAPP_REG_U8_SOFTWARE_RESET,  			     SMIAPP_SOFTWARE_RESET); -	if (gpio_is_valid(sensor->platform_data->xshutdown)) -		gpio_set_value(sensor->platform_data->xshutdown, 0); -	if (sensor->platform_data->set_xclk) -		sensor->platform_data->set_xclk(&sensor->src->sd, 0); -	else -		clk_disable_unprepare(sensor->ext_clk); +	gpiod_set_value(sensor->xshutdown, 0); +	clk_disable_unprepare(sensor->ext_clk);  	usleep_range(5000, 5000);  	regulator_disable(sensor->vana);  	sensor->streaming = false; @@ -1491,8 +1486,8 @@ static int smiapp_start_streaming(struct smiapp_sensor *sensor)  	if ((sensor->limits[SMIAPP_LIMIT_FLASH_MODE_CAPABILITY] &  	     (SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE |  	      SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE)) && -	    sensor->platform_data->strobe_setup != NULL && -	    sensor->platform_data->strobe_setup->trigger != 0) { +	    sensor->hwcfg->strobe_setup != NULL && +	    sensor->hwcfg->strobe_setup->trigger != 0) {  		rval = smiapp_setup_flash_strobe(sensor);  		if (rval)  			goto out; @@ -2309,7 +2304,7 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,  	if (!sensor->nvm_size) {  		/* NVM not read yet - read it now */ -		sensor->nvm_size = sensor->platform_data->nvm_size; +		sensor->nvm_size = sensor->hwcfg->nvm_size;  		if (smiapp_set_power(subdev, 1) < 0)  			return -ENODEV;  		if (smiapp_read_nvm(sensor, sensor->nvm)) { @@ -2554,35 +2549,27 @@ static int smiapp_init(struct smiapp_sensor *sensor)  		return PTR_ERR(sensor->vana);  	} -	if (!sensor->platform_data->set_xclk) { -		sensor->ext_clk = devm_clk_get(&client->dev, NULL); -		if (IS_ERR(sensor->ext_clk)) { -			dev_err(&client->dev, "could not get clock\n"); -			return PTR_ERR(sensor->ext_clk); -		} - -		rval = clk_set_rate(sensor->ext_clk, -				    sensor->platform_data->ext_clk); -		if (rval < 0) { -			dev_err(&client->dev, -				"unable to set clock freq to %u\n", -				sensor->platform_data->ext_clk); -			return rval; -		} +	sensor->ext_clk = devm_clk_get(&client->dev, NULL); +	if (IS_ERR(sensor->ext_clk)) { +		dev_err(&client->dev, "could not get clock (%ld)\n", +			PTR_ERR(sensor->ext_clk)); +		return -EPROBE_DEFER;  	} -	if (gpio_is_valid(sensor->platform_data->xshutdown)) { -		rval = devm_gpio_request_one( -			&client->dev, sensor->platform_data->xshutdown, 0, -			"SMIA++ xshutdown"); -		if (rval < 0) { -			dev_err(&client->dev, -				"unable to acquire reset gpio %d\n", -				sensor->platform_data->xshutdown); -			return rval; -		} +	rval = clk_set_rate(sensor->ext_clk, +			    sensor->hwcfg->ext_clk); +	if (rval < 0) { +		dev_err(&client->dev, +			"unable to set clock freq to %u\n", +			sensor->hwcfg->ext_clk); +		return rval;  	} +	sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown", +						    GPIOD_OUT_LOW); +	if (IS_ERR(sensor->xshutdown)) +		return PTR_ERR(sensor->xshutdown); +  	rval = smiapp_power_on(sensor);  	if (rval)  		return -ENODEV; @@ -2612,7 +2599,7 @@ static int smiapp_init(struct smiapp_sensor *sensor)  	 *  	 * Rotation also changes the bayer pattern.  	 */ -	if (sensor->platform_data->module_board_orient == +	if (sensor->hwcfg->module_board_orient ==  	    SMIAPP_MODULE_BOARD_ORIENT_180)  		sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP |  					  SMIAPP_IMAGE_ORIENTATION_VFLIP; @@ -2661,9 +2648,9 @@ static int smiapp_init(struct smiapp_sensor *sensor)  	/* SMIA++ NVM initialization - it will be read from the sensor  	 * when it is first requested by userspace.  	 */ -	if (sensor->minfo.smiapp_version && sensor->platform_data->nvm_size) { +	if (sensor->minfo.smiapp_version && sensor->hwcfg->nvm_size) {  		sensor->nvm = devm_kzalloc(&client->dev, -				sensor->platform_data->nvm_size, GFP_KERNEL); +				sensor->hwcfg->nvm_size, GFP_KERNEL);  		if (sensor->nvm == NULL) {  			dev_err(&client->dev, "nvm buf allocation failed\n");  			rval = -ENOMEM; @@ -2706,8 +2693,8 @@ static int smiapp_init(struct smiapp_sensor *sensor)  	/* prepare PLL configuration input values */  	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2; -	pll->csi2.lanes = sensor->platform_data->lanes; -	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk; +	pll->csi2.lanes = sensor->hwcfg->lanes; +	pll->ext_clk_freq_hz = sensor->hwcfg->ext_clk;  	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];  	/* Profile 0 sensors have no separate OP clock branch. */  	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) @@ -2984,9 +2971,9 @@ static int smiapp_resume(struct device *dev)  #endif /* CONFIG_PM */ -static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev) +static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)  { -	struct smiapp_platform_data *pdata; +	struct smiapp_hwconfig *hwcfg;  	struct v4l2_of_endpoint *bus_cfg;  	struct device_node *ep;  	int i; @@ -3003,58 +2990,55 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)  	if (IS_ERR(bus_cfg))  		goto out_err; -	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); -	if (!pdata) +	hwcfg = devm_kzalloc(dev, sizeof(*hwcfg), GFP_KERNEL); +	if (!hwcfg)  		goto out_err;  	switch (bus_cfg->bus_type) {  	case V4L2_MBUS_CSI2: -		pdata->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2; +		hwcfg->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2;  		break;  		/* FIXME: add CCP2 support. */  	default:  		goto out_err;  	} -	pdata->lanes = bus_cfg->bus.mipi_csi2.num_data_lanes; -	dev_dbg(dev, "lanes %u\n", pdata->lanes); - -	/* xshutdown GPIO is optional */ -	pdata->xshutdown = of_get_named_gpio(dev->of_node, "reset-gpios", 0); +	hwcfg->lanes = bus_cfg->bus.mipi_csi2.num_data_lanes; +	dev_dbg(dev, "lanes %u\n", hwcfg->lanes);  	/* NVM size is not mandatory */  	of_property_read_u32(dev->of_node, "nokia,nvm-size", -				    &pdata->nvm_size); +				    &hwcfg->nvm_size);  	rval = of_property_read_u32(dev->of_node, "clock-frequency", -				    &pdata->ext_clk); +				    &hwcfg->ext_clk);  	if (rval) {  		dev_warn(dev, "can't get clock-frequency\n");  		goto out_err;  	} -	dev_dbg(dev, "reset %d, nvm %d, clk %d, csi %d\n", pdata->xshutdown, -		pdata->nvm_size, pdata->ext_clk, pdata->csi_signalling_mode); +	dev_dbg(dev, "nvm %d, clk %d, csi %d\n", hwcfg->nvm_size, +		hwcfg->ext_clk, hwcfg->csi_signalling_mode);  	if (!bus_cfg->nr_of_link_frequencies) {  		dev_warn(dev, "no link frequencies defined\n");  		goto out_err;  	} -	pdata->op_sys_clock = devm_kcalloc( +	hwcfg->op_sys_clock = devm_kcalloc(  		dev, bus_cfg->nr_of_link_frequencies + 1 /* guardian */, -		sizeof(*pdata->op_sys_clock), GFP_KERNEL); -	if (!pdata->op_sys_clock) +		sizeof(*hwcfg->op_sys_clock), GFP_KERNEL); +	if (!hwcfg->op_sys_clock)  		goto out_err;  	for (i = 0; i < bus_cfg->nr_of_link_frequencies; i++) { -		pdata->op_sys_clock[i] = bus_cfg->link_frequencies[i]; -		dev_dbg(dev, "freq %d: %lld\n", i, pdata->op_sys_clock[i]); +		hwcfg->op_sys_clock[i] = bus_cfg->link_frequencies[i]; +		dev_dbg(dev, "freq %d: %lld\n", i, hwcfg->op_sys_clock[i]);  	}  	v4l2_of_free_endpoint(bus_cfg);  	of_node_put(ep); -	return pdata; +	return hwcfg;  out_err:  	v4l2_of_free_endpoint(bus_cfg); @@ -3066,17 +3050,17 @@ static int smiapp_probe(struct i2c_client *client,  			const struct i2c_device_id *devid)  {  	struct smiapp_sensor *sensor; -	struct smiapp_platform_data *pdata = smiapp_get_pdata(&client->dev); +	struct smiapp_hwconfig *hwcfg = smiapp_get_hwconfig(&client->dev);  	int rval; -	if (pdata == NULL) +	if (hwcfg == NULL)  		return -ENODEV;  	sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);  	if (sensor == NULL)  		return -ENOMEM; -	sensor->platform_data = pdata; +	sensor->hwcfg = hwcfg;  	mutex_init(&sensor->mutex);  	mutex_init(&sensor->power_mutex);  	sensor->src = &sensor->ssds[sensor->ssds_used]; @@ -3119,12 +3103,8 @@ static int smiapp_remove(struct i2c_client *client)  	v4l2_async_unregister_subdev(subdev);  	if (sensor->power_count) { -		if (gpio_is_valid(sensor->platform_data->xshutdown)) -			gpio_set_value(sensor->platform_data->xshutdown, 0); -		if (sensor->platform_data->set_xclk) -			sensor->platform_data->set_xclk(&sensor->src->sd, 0); -		else -			clk_disable_unprepare(sensor->ext_clk); +		gpiod_set_value(sensor->xshutdown, 0); +		clk_disable_unprepare(sensor->ext_clk);  		sensor->power_count = 0;  	} diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c index abf9ea7a0fb7..cb128eae9c54 100644 --- a/drivers/media/i2c/smiapp/smiapp-quirk.c +++ b/drivers/media/i2c/smiapp/smiapp-quirk.c @@ -26,7 +26,7 @@ static int smiapp_write_8(struct smiapp_sensor *sensor, u16 reg, u8 val)  }  static int smiapp_write_8s(struct smiapp_sensor *sensor, -			   struct smiapp_reg_8 *regs, int len) +			   const struct smiapp_reg_8 *regs, int len)  {  	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);  	int rval; @@ -71,7 +71,7 @@ static int jt8ew9_limits(struct smiapp_sensor *sensor)  static int jt8ew9_post_poweron(struct smiapp_sensor *sensor)  { -	struct smiapp_reg_8 regs[] = { +	const struct smiapp_reg_8 regs[] = {  		{ 0x30a3, 0xd8 }, /* Output port control : LVDS ports only */  		{ 0x30ae, 0x00 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */  		{ 0x30af, 0xd0 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */ @@ -115,7 +115,7 @@ const struct smiapp_quirk smiapp_jt8ew9_quirk = {  static int imx125es_post_poweron(struct smiapp_sensor *sensor)  {  	/* Taken from v02. No idea what the other two are. */ -	struct smiapp_reg_8 regs[] = { +	const struct smiapp_reg_8 regs[] = {  		/*  		 * 0x3302: clk during frame blanking:  		 * 0x00 - HS mode, 0x01 - LP11 @@ -145,8 +145,7 @@ static int jt8ev1_post_poweron(struct smiapp_sensor *sensor)  {  	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);  	int rval; - -	struct smiapp_reg_8 regs[] = { +	const struct smiapp_reg_8 regs[] = {  		{ 0x3031, 0xcd }, /* For digital binning (EQ_MONI) */  		{ 0x30a3, 0xd0 }, /* FLASH STROBE enable */  		{ 0x3237, 0x00 }, /* For control of pulse timing for ADC */ @@ -167,8 +166,7 @@ static int jt8ev1_post_poweron(struct smiapp_sensor *sensor)  		{ 0x33cf, 0xec }, /* For Black sun */  		{ 0x3328, 0x80 }, /* Ugh. No idea what's this. */  	}; - -	struct smiapp_reg_8 regs_96[] = { +	const struct smiapp_reg_8 regs_96[] = {  		{ 0x30ae, 0x00 }, /* For control of ADC clock */  		{ 0x30af, 0xd0 },  		{ 0x30b0, 0x01 }, @@ -178,13 +176,13 @@ static int jt8ev1_post_poweron(struct smiapp_sensor *sensor)  	if (rval < 0)  		return rval; -	switch (sensor->platform_data->ext_clk) { +	switch (sensor->hwcfg->ext_clk) {  	case 9600000:  		return smiapp_write_8s(sensor, regs_96,  				       ARRAY_SIZE(regs_96));  	default:  		dev_warn(&client->dev, "no MSRs for %d Hz ext_clk\n", -			 sensor->platform_data->ext_clk); +			 sensor->hwcfg->ext_clk);  		return 0;  	}  } diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c index 6b6c20b61397..1e501c06d18c 100644 --- a/drivers/media/i2c/smiapp/smiapp-regs.c +++ b/drivers/media/i2c/smiapp/smiapp-regs.c @@ -188,7 +188,8 @@ int smiapp_read_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 *val)  				   SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY));  } -int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val) +static int smiapp_read_quirk(struct smiapp_sensor *sensor, u32 reg, u32 *val, +			     bool force8)  {  	int rval; @@ -199,21 +200,20 @@ int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)  	if (rval < 0)  		return rval; +	if (force8) +		return __smiapp_read(sensor, reg, val, true); +  	return smiapp_read_no_quirk(sensor, reg, val);  } -int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val) +int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)  { -	int rval; - -	*val = 0; -	rval = smiapp_call_quirk(sensor, reg_access, false, ®, val); -	if (rval == -ENOIOCTLCMD) -		return 0; -	if (rval < 0) -		return rval; +	return smiapp_read_quirk(sensor, reg, val, false); +} -	return __smiapp_read(sensor, reg, val, true); +int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val) +{ +	return smiapp_read_quirk(sensor, reg, val, true);  }  int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val) diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h index 2174f89a00db..aae72bc87bf7 100644 --- a/drivers/media/i2c/smiapp/smiapp.h +++ b/drivers/media/i2c/smiapp/smiapp.h @@ -151,7 +151,7 @@ struct smiapp_csi_data_format {  #define SMIAPP_PADS			2  #define SMIAPP_COMPRESSED_BASE		8 -#define SMIAPP_COMPRESSED_MAX		12 +#define SMIAPP_COMPRESSED_MAX		16  #define SMIAPP_NR_OF_COMPRESSED		(SMIAPP_COMPRESSED_MAX - \  					 SMIAPP_COMPRESSED_BASE + 1) @@ -197,9 +197,10 @@ struct smiapp_sensor {  	struct smiapp_subdev *binner;  	struct smiapp_subdev *scaler;  	struct smiapp_subdev *pixel_array; -	struct smiapp_platform_data *platform_data; +	struct smiapp_hwconfig *hwcfg;  	struct regulator *vana;  	struct clk *ext_clk; +	struct gpio_desc *xshutdown;  	u32 limits[SMIAPP_LIMIT_LAST];  	u8 nbinning_subtypes;  	struct smiapp_binning_subtype binning_subtypes[SMIAPP_BINNING_SUBTYPES]; diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig index 23d352f0adf0..7704bcf5cc25 100644 --- a/drivers/media/i2c/soc_camera/Kconfig +++ b/drivers/media/i2c/soc_camera/Kconfig @@ -14,11 +14,14 @@ config SOC_CAMERA_MT9M001  	  and colour models.  config SOC_CAMERA_MT9M111 -	tristate "mt9m111, mt9m112 and mt9m131 support" +	tristate "legacy soc_camera mt9m111, mt9m112 and mt9m131 support"  	depends on SOC_CAMERA && I2C +	select VIDEO_MT9M111  	help  	  This driver supports MT9M111, MT9M112 and MT9M131 cameras from -	  Micron/Aptina +	  Micron/Aptina. +	  This is the legacy configuration which shouldn't be used anymore, +	  while VIDEO_MT9M111 should be used instead.  config SOC_CAMERA_MT9T031  	tristate "mt9t031 support" diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile index d0421feaa796..6f994f9353a0 100644 --- a/drivers/media/i2c/soc_camera/Makefile +++ b/drivers/media/i2c/soc_camera/Makefile @@ -1,6 +1,5 @@  obj-$(CONFIG_SOC_CAMERA_IMX074)		+= imx074.o  obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o -obj-$(CONFIG_SOC_CAMERA_MT9M111)	+= mt9m111.o  obj-$(CONFIG_SOC_CAMERA_MT9T031)	+= mt9t031.o  obj-$(CONFIG_SOC_CAMERA_MT9T112)	+= mt9t112.o  obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c index f68c2352c63c..05b55cfe8147 100644 --- a/drivers/media/i2c/soc_camera/imx074.c +++ b/drivers/media/i2c/soc_camera/imx074.c @@ -209,31 +209,26 @@ static int imx074_get_fmt(struct v4l2_subdev *sd,  	return 0;  } -static int imx074_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int imx074_get_selection(struct v4l2_subdev *sd, +				struct v4l2_subdev_pad_config *cfg, +				struct v4l2_subdev_selection *sel)  { -	struct v4l2_rect *rect = &a->c; - -	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	rect->top	= 0; -	rect->left	= 0; -	rect->width	= IMX074_WIDTH; -	rect->height	= IMX074_HEIGHT; - -	return 0; -} +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -static int imx074_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	a->bounds.left			= 0; -	a->bounds.top			= 0; -	a->bounds.width			= IMX074_WIDTH; -	a->bounds.height		= IMX074_HEIGHT; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	sel->r.left = 0; +	sel->r.top = 0; +	sel->r.width = IMX074_WIDTH; +	sel->r.height = IMX074_HEIGHT; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +	case V4L2_SEL_TGT_CROP: +		return 0; +	default: +		return -EINVAL; +	}  }  static int imx074_enum_mbus_code(struct v4l2_subdev *sd, @@ -278,8 +273,6 @@ static int imx074_g_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {  	.s_stream	= imx074_s_stream, -	.g_crop		= imx074_g_crop, -	.cropcap	= imx074_cropcap,  	.g_mbus_config	= imx074_g_mbus_config,  }; @@ -289,6 +282,7 @@ static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {  static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = {  	.enum_mbus_code = imx074_enum_mbus_code, +	.get_selection	= imx074_get_selection,  	.get_fmt	= imx074_get_fmt,  	.set_fmt	= imx074_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index 69becc358659..3d6378d4491c 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -171,13 +171,19 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)  	return 0;  } -static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int mt9m001_set_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9m001 *mt9m001 = to_mt9m001(client); -	struct v4l2_rect rect = a->c; -	int ret; +	struct v4l2_rect rect = sel->r;  	const u16 hblank = 9, vblank = 25; +	int ret; + +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP) +		return -EINVAL;  	if (mt9m001->fmts == mt9m001_colour_fmts)  		/* @@ -225,29 +231,30 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)  	return ret;  } -static int mt9m001_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9m001_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9m001 *mt9m001 = to_mt9m001(client); -	a->c	= mt9m001->rect; -	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	a->bounds.left			= MT9M001_COLUMN_SKIP; -	a->bounds.top			= MT9M001_ROW_SKIP; -	a->bounds.width			= MT9M001_MAX_WIDTH; -	a->bounds.height		= MT9M001_MAX_HEIGHT; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = MT9M001_COLUMN_SKIP; +		sel->r.top = MT9M001_ROW_SKIP; +		sel->r.width = MT9M001_MAX_WIDTH; +		sel->r.height = MT9M001_MAX_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = mt9m001->rect; +		return 0; +	default: +		return -EINVAL; +	}  }  static int mt9m001_get_fmt(struct v4l2_subdev *sd, @@ -275,18 +282,18 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd,  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9m001 *mt9m001 = to_mt9m001(client); -	struct v4l2_crop a = { -		.c = { -			.left	= mt9m001->rect.left, -			.top	= mt9m001->rect.top, -			.width	= mf->width, -			.height	= mf->height, -		}, +	struct v4l2_subdev_selection sel = { +		.which = V4L2_SUBDEV_FORMAT_ACTIVE, +		.target = V4L2_SEL_TGT_CROP, +		.r.left = mt9m001->rect.left, +		.r.top = mt9m001->rect.top, +		.r.width = mf->width, +		.r.height = mf->height,  	};  	int ret;  	/* No support for scaling so far, just crop. TODO: use skipping */ -	ret = mt9m001_s_crop(sd, &a); +	ret = mt9m001_set_selection(sd, NULL, &sel);  	if (!ret) {  		mf->width	= mt9m001->rect.width;  		mf->height	= mt9m001->rect.height; @@ -625,9 +632,6 @@ static int mt9m001_s_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {  	.s_stream	= mt9m001_s_stream, -	.s_crop		= mt9m001_s_crop, -	.g_crop		= mt9m001_g_crop, -	.cropcap	= mt9m001_cropcap,  	.g_mbus_config	= mt9m001_g_mbus_config,  	.s_mbus_config	= mt9m001_s_mbus_config,  }; @@ -638,6 +642,8 @@ static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {  static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = {  	.enum_mbus_code = mt9m001_enum_mbus_code, +	.get_selection	= mt9m001_get_selection, +	.set_selection	= mt9m001_set_selection,  	.get_fmt	= mt9m001_get_fmt,  	.set_fmt	= mt9m001_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 5c8e3ffe3b27..3aa5569065ad 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -264,7 +264,7 @@ static int mt9t031_set_params(struct i2c_client *client,  	/*  	 * The caller provides a supported format, as guaranteed by -	 * .set_fmt(FORMAT_TRY), soc_camera_s_crop() and soc_camera_cropcap() +	 * .set_fmt(FORMAT_TRY), soc_camera_s_selection() and soc_camera_cropcap()  	 */  	if (ret >= 0)  		ret = reg_write(client, MT9T031_COLUMN_START, rect->left); @@ -294,11 +294,17 @@ static int mt9t031_set_params(struct i2c_client *client,  	return ret < 0 ? ret : 0;  } -static int mt9t031_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int mt9t031_set_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  { -	struct v4l2_rect rect = a->c;  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9t031 *mt9t031 = to_mt9t031(client); +	struct v4l2_rect rect = sel->r; + +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP) +		return -EINVAL;  	rect.width = ALIGN(rect.width, 2);  	rect.height = ALIGN(rect.height, 2); @@ -312,29 +318,30 @@ static int mt9t031_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)  	return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip);  } -static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9t031_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9t031 *mt9t031 = to_mt9t031(client); -	a->c	= mt9t031->rect; -	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	a->bounds.left			= MT9T031_COLUMN_SKIP; -	a->bounds.top			= MT9T031_ROW_SKIP; -	a->bounds.width			= MT9T031_MAX_WIDTH; -	a->bounds.height		= MT9T031_MAX_HEIGHT; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = MT9T031_COLUMN_SKIP; +		sel->r.top = MT9T031_ROW_SKIP; +		sel->r.width = MT9T031_MAX_WIDTH; +		sel->r.height = MT9T031_MAX_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = mt9t031->rect; +		return 0; +	default: +		return -EINVAL; +	}  }  static int mt9t031_get_fmt(struct v4l2_subdev *sd, @@ -721,9 +728,6 @@ static int mt9t031_s_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {  	.s_stream	= mt9t031_s_stream, -	.s_crop		= mt9t031_s_crop, -	.g_crop		= mt9t031_g_crop, -	.cropcap	= mt9t031_cropcap,  	.g_mbus_config	= mt9t031_g_mbus_config,  	.s_mbus_config	= mt9t031_s_mbus_config,  }; @@ -734,6 +738,8 @@ static const struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = {  static const struct v4l2_subdev_pad_ops mt9t031_subdev_pad_ops = {  	.enum_mbus_code = mt9t031_enum_mbus_code, +	.get_selection	= mt9t031_get_selection, +	.set_selection	= mt9t031_set_selection,  	.get_fmt	= mt9t031_get_fmt,  	.set_fmt	= mt9t031_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c index 6a1b2a9f9a09..2ef22241ec14 100644 --- a/drivers/media/i2c/soc_camera/mt9t112.c +++ b/drivers/media/i2c/soc_camera/mt9t112.c @@ -867,39 +867,48 @@ static int mt9t112_set_params(struct mt9t112_priv *priv,  	return 0;  } -static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	a->bounds.left			= 0; -	a->bounds.top			= 0; -	a->bounds.width			= MAX_WIDTH; -	a->bounds.height		= MAX_HEIGHT; -	a->defrect.left			= 0; -	a->defrect.top			= 0; -	a->defrect.width		= VGA_WIDTH; -	a->defrect.height		= VGA_HEIGHT; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; - -	return 0; -} - -static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9t112_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9t112_priv *priv = to_mt9t112(client); -	a->c	= priv->frame; -	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +		sel->r.left = 0; +		sel->r.top = 0; +		sel->r.width = MAX_WIDTH; +		sel->r.height = MAX_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = 0; +		sel->r.top = 0; +		sel->r.width = VGA_WIDTH; +		sel->r.height = VGA_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = priv->frame; +		return 0; +	default: +		return -EINVAL; +	}  } -static int mt9t112_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int mt9t112_set_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9t112_priv *priv = to_mt9t112(client); -	const struct v4l2_rect *rect = &a->c; +	const struct v4l2_rect *rect = &sel->r; + +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP) +		return -EINVAL;  	return mt9t112_set_params(priv, rect, priv->format->code);  } @@ -1024,15 +1033,14 @@ static int mt9t112_s_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {  	.s_stream	= mt9t112_s_stream, -	.cropcap	= mt9t112_cropcap, -	.g_crop		= mt9t112_g_crop, -	.s_crop		= mt9t112_s_crop,  	.g_mbus_config	= mt9t112_g_mbus_config,  	.s_mbus_config	= mt9t112_s_mbus_config,  };  static const struct v4l2_subdev_pad_ops mt9t112_subdev_pad_ops = {  	.enum_mbus_code = mt9t112_enum_mbus_code, +	.get_selection	= mt9t112_get_selection, +	.set_selection	= mt9t112_set_selection,  	.get_fmt	= mt9t112_get_fmt,  	.set_fmt	= mt9t112_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index 2721e583bfa0..6a14ab5e4f2d 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -276,14 +276,20 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)  	return 0;  } -static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int mt9v022_set_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9v022 *mt9v022 = to_mt9v022(client); -	struct v4l2_rect rect = a->c; +	struct v4l2_rect rect = sel->r;  	int min_row, min_blank;  	int ret; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP) +		return -EINVAL; +  	/* Bayer format - even size lengths */  	if (mt9v022->fmts == mt9v022_colour_fmts) {  		rect.width	= ALIGN(rect.width, 2); @@ -350,29 +356,30 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)  	return 0;  } -static int mt9v022_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9v022_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9v022 *mt9v022 = to_mt9v022(client); -	a->c	= mt9v022->rect; -	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	a->bounds.left			= MT9V022_COLUMN_SKIP; -	a->bounds.top			= MT9V022_ROW_SKIP; -	a->bounds.width			= MT9V022_MAX_WIDTH; -	a->bounds.height		= MT9V022_MAX_HEIGHT; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = MT9V022_COLUMN_SKIP; +		sel->r.top = MT9V022_ROW_SKIP; +		sel->r.width = MT9V022_MAX_WIDTH; +		sel->r.height = MT9V022_MAX_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = mt9v022->rect; +		return 0; +	default: +		return -EINVAL; +	}  }  static int mt9v022_get_fmt(struct v4l2_subdev *sd, @@ -400,13 +407,13 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct mt9v022 *mt9v022 = to_mt9v022(client); -	struct v4l2_crop a = { -		.c = { -			.left	= mt9v022->rect.left, -			.top	= mt9v022->rect.top, -			.width	= mf->width, -			.height	= mf->height, -		}, +	struct v4l2_subdev_selection sel = { +		.which = V4L2_SUBDEV_FORMAT_ACTIVE, +		.target = V4L2_SEL_TGT_CROP, +		.r.left = mt9v022->rect.left, +		.r.top = mt9v022->rect.top, +		.r.width = mf->width, +		.r.height = mf->height,  	};  	int ret; @@ -430,7 +437,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,  	}  	/* No support for scaling on this camera, just crop. */ -	ret = mt9v022_s_crop(sd, &a); +	ret = mt9v022_set_selection(sd, NULL, &sel);  	if (!ret) {  		mf->width	= mt9v022->rect.width;  		mf->height	= mt9v022->rect.height; @@ -853,9 +860,6 @@ static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {  	.s_stream	= mt9v022_s_stream, -	.s_crop		= mt9v022_s_crop, -	.g_crop		= mt9v022_g_crop, -	.cropcap	= mt9v022_cropcap,  	.g_mbus_config	= mt9v022_g_mbus_config,  	.s_mbus_config	= mt9v022_s_mbus_config,  }; @@ -866,6 +870,8 @@ static const struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {  static const struct v4l2_subdev_pad_ops mt9v022_subdev_pad_ops = {  	.enum_mbus_code = mt9v022_enum_mbus_code, +	.get_selection	= mt9v022_get_selection, +	.set_selection	= mt9v022_set_selection,  	.get_fmt	= mt9v022_get_fmt,  	.set_fmt	= mt9v022_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c index 9b4f5deec748..56de18263359 100644 --- a/drivers/media/i2c/soc_camera/ov2640.c +++ b/drivers/media/i2c/soc_camera/ov2640.c @@ -928,29 +928,25 @@ static int ov2640_enum_mbus_code(struct v4l2_subdev *sd,  	return 0;  } -static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) -{ -	a->c.left	= 0; -	a->c.top	= 0; -	a->c.width	= UXGA_WIDTH; -	a->c.height	= UXGA_HEIGHT; -	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +static int ov2640_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  { -	a->bounds.left			= 0; -	a->bounds.top			= 0; -	a->bounds.width			= UXGA_WIDTH; -	a->bounds.height		= UXGA_HEIGHT; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +	case V4L2_SEL_TGT_CROP: +		sel->r.left = 0; +		sel->r.top = 0; +		sel->r.width = UXGA_WIDTH; +		sel->r.height = UXGA_HEIGHT; +		return 0; +	default: +		return -EINVAL; +	}  }  static int ov2640_video_probe(struct i2c_client *client) @@ -1024,13 +1020,12 @@ static int ov2640_g_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {  	.s_stream	= ov2640_s_stream, -	.cropcap	= ov2640_cropcap, -	.g_crop		= ov2640_g_crop,  	.g_mbus_config	= ov2640_g_mbus_config,  };  static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {  	.enum_mbus_code = ov2640_enum_mbus_code, +	.get_selection	= ov2640_get_selection,  	.get_fmt	= ov2640_get_fmt,  	.set_fmt	= ov2640_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c index bab9ac0c1764..3d185bd622a3 100644 --- a/drivers/media/i2c/soc_camera/ov5642.c +++ b/drivers/media/i2c/soc_camera/ov5642.c @@ -850,13 +850,19 @@ static int ov5642_enum_mbus_code(struct v4l2_subdev *sd,  	return 0;  } -static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int ov5642_set_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct ov5642 *priv = to_ov5642(client); -	struct v4l2_rect rect = a->c; +	struct v4l2_rect rect = sel->r;  	int ret; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP) +		return -EINVAL; +  	v4l_bound_align_image(&rect.width, 48, OV5642_MAX_WIDTH, 1,  			      &rect.height, 32, OV5642_MAX_HEIGHT, 1, 0); @@ -878,32 +884,30 @@ static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)  	return ret;  } -static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int ov5642_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct ov5642 *priv = to_ov5642(client); -	struct v4l2_rect *rect = &a->c; -	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)  		return -EINVAL; -	*rect = priv->crop_rect; - -	return 0; -} - -static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	a->bounds.left			= 0; -	a->bounds.top			= 0; -	a->bounds.width			= OV5642_MAX_WIDTH; -	a->bounds.height		= OV5642_MAX_HEIGHT; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; - -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = 0; +		sel->r.top = 0; +		sel->r.width = OV5642_MAX_WIDTH; +		sel->r.height = OV5642_MAX_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = priv->crop_rect; +		return 0; +	default: +		return -EINVAL; +	}  }  static int ov5642_g_mbus_config(struct v4l2_subdev *sd, @@ -940,14 +944,13 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on)  }  static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = { -	.s_crop		= ov5642_s_crop, -	.g_crop		= ov5642_g_crop, -	.cropcap	= ov5642_cropcap,  	.g_mbus_config	= ov5642_g_mbus_config,  };  static const struct v4l2_subdev_pad_ops ov5642_subdev_pad_ops = {  	.enum_mbus_code = ov5642_enum_mbus_code, +	.get_selection	= ov5642_get_selection, +	.set_selection	= ov5642_set_selection,  	.get_fmt	= ov5642_get_fmt,  	.set_fmt	= ov5642_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index 1f8af1ee8352..4bf2995e1cb8 100644 --- a/drivers/media/i2c/soc_camera/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c @@ -432,25 +432,43 @@ static int ov6650_s_power(struct v4l2_subdev *sd, int on)  	return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);  } -static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int ov6650_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct ov6650 *priv = to_ov6650(client); -	a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->c = priv->rect; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = DEF_HSTRT << 1; +		sel->r.top = DEF_VSTRT << 1; +		sel->r.width = W_CIF; +		sel->r.height = H_CIF; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = priv->rect; +		return 0; +	default: +		return -EINVAL; +	}  } -static int ov6650_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int ov6650_set_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct ov6650 *priv = to_ov6650(client); -	struct v4l2_rect rect = a->c; +	struct v4l2_rect rect = sel->r;  	int ret; -	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP)  		return -EINVAL;  	rect.left   = ALIGN(rect.left,   2); @@ -483,22 +501,6 @@ static int ov6650_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)  	return ret;  } -static int ov6650_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -		return -EINVAL; - -	a->bounds.left			= DEF_HSTRT << 1; -	a->bounds.top			= DEF_VSTRT << 1; -	a->bounds.width			= W_CIF; -	a->bounds.height		= H_CIF; -	a->defrect			= a->bounds; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; - -	return 0; -} -  static int ov6650_get_fmt(struct v4l2_subdev *sd,  		struct v4l2_subdev_pad_config *cfg,  		struct v4l2_subdev_format *format) @@ -549,16 +551,15 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)  	struct soc_camera_sense *sense = icd->sense;  	struct ov6650 *priv = to_ov6650(client);  	bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect); -	struct v4l2_crop a = { -		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE, -		.c = { -			.left	= priv->rect.left + (priv->rect.width >> 1) - -					(mf->width >> (1 - half_scale)), -			.top	= priv->rect.top + (priv->rect.height >> 1) - -					(mf->height >> (1 - half_scale)), -			.width	= mf->width << half_scale, -			.height	= mf->height << half_scale, -		}, +	struct v4l2_subdev_selection sel = { +		.which = V4L2_SUBDEV_FORMAT_ACTIVE, +		.target = V4L2_SEL_TGT_CROP, +		.r.left = priv->rect.left + (priv->rect.width >> 1) - +			(mf->width >> (1 - half_scale)), +		.r.top = priv->rect.top + (priv->rect.height >> 1) - +			(mf->height >> (1 - half_scale)), +		.r.width = mf->width << half_scale, +		.r.height = mf->height << half_scale,  	};  	u32 code = mf->code;  	unsigned long mclk, pclk; @@ -672,7 +673,7 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)  	dev_dbg(&client->dev, "pixel clock divider: %ld.%ld\n",  			mclk / pclk, 10 * mclk % pclk / pclk); -	ret = ov6650_s_crop(sd, &a); +	ret = ov6650_set_selection(sd, NULL, &sel);  	if (!ret)  		ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask);  	if (!ret) @@ -943,9 +944,6 @@ static int ov6650_s_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops ov6650_video_ops = {  	.s_stream	= ov6650_s_stream, -	.cropcap	= ov6650_cropcap, -	.g_crop		= ov6650_g_crop, -	.s_crop		= ov6650_s_crop,  	.g_parm		= ov6650_g_parm,  	.s_parm		= ov6650_s_parm,  	.g_mbus_config	= ov6650_g_mbus_config, @@ -954,6 +952,8 @@ static struct v4l2_subdev_video_ops ov6650_video_ops = {  static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {  	.enum_mbus_code = ov6650_enum_mbus_code, +	.get_selection	= ov6650_get_selection, +	.set_selection	= ov6650_set_selection,  	.get_fmt	= ov6650_get_fmt,  	.set_fmt	= ov6650_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index a43410c1e254..7e68762b3a4b 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c @@ -851,29 +851,28 @@ ov772x_set_fmt_error:  	return ret;  } -static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) -{ -	a->c.left	= 0; -	a->c.top	= 0; -	a->c.width	= VGA_WIDTH; -	a->c.height	= VGA_HEIGHT; -	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +static int ov772x_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  { -	a->bounds.left			= 0; -	a->bounds.top			= 0; -	a->bounds.width			= OV772X_MAX_WIDTH; -	a->bounds.height		= OV772X_MAX_HEIGHT; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	sel->r.left = 0; +	sel->r.top = 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.width = OV772X_MAX_WIDTH; +		sel->r.height = OV772X_MAX_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r.width = VGA_WIDTH; +		sel->r.height = VGA_HEIGHT; +		return 0; +	default: +		return -EINVAL; +	}  }  static int ov772x_get_fmt(struct v4l2_subdev *sd, @@ -1030,13 +1029,12 @@ static int ov772x_g_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {  	.s_stream	= ov772x_s_stream, -	.cropcap	= ov772x_cropcap, -	.g_crop		= ov772x_g_crop,  	.g_mbus_config	= ov772x_g_mbus_config,  };  static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = {  	.enum_mbus_code = ov772x_enum_mbus_code, +	.get_selection	= ov772x_get_selection,  	.get_fmt	= ov772x_get_fmt,  	.set_fmt	= ov772x_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index 8caae1c07541..8c93c57af71c 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c @@ -561,29 +561,25 @@ static int ov9640_enum_mbus_code(struct v4l2_subdev *sd,  	return 0;  } -static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) -{ -	a->c.left	= 0; -	a->c.top	= 0; -	a->c.width	= W_SXGA; -	a->c.height	= H_SXGA; -	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +static int ov9640_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  { -	a->bounds.left			= 0; -	a->bounds.top			= 0; -	a->bounds.width			= W_SXGA; -	a->bounds.height		= H_SXGA; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	sel->r.left = 0; +	sel->r.top = 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +	case V4L2_SEL_TGT_CROP: +		sel->r.width = W_SXGA; +		sel->r.height = H_SXGA; +		return 0; +	default: +		return -EINVAL; +	}  }  static int ov9640_video_probe(struct i2c_client *client) @@ -667,13 +663,12 @@ static int ov9640_g_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops ov9640_video_ops = {  	.s_stream	= ov9640_s_stream, -	.cropcap	= ov9640_cropcap, -	.g_crop		= ov9640_g_crop,  	.g_mbus_config	= ov9640_g_mbus_config,  };  static const struct v4l2_subdev_pad_ops ov9640_pad_ops = {  	.enum_mbus_code = ov9640_enum_mbus_code, +	.get_selection	= ov9640_get_selection,  	.set_fmt	= ov9640_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c index 03a7fc7316ae..0da632d7d33a 100644 --- a/drivers/media/i2c/soc_camera/ov9740.c +++ b/drivers/media/i2c/soc_camera/ov9740.c @@ -737,29 +737,25 @@ static int ov9740_enum_mbus_code(struct v4l2_subdev *sd,  	return 0;  } -static int ov9740_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	a->bounds.left		= 0; -	a->bounds.top		= 0; -	a->bounds.width		= OV9740_MAX_WIDTH; -	a->bounds.height	= OV9740_MAX_HEIGHT; -	a->defrect		= a->bounds; -	a->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; - -	return 0; -} - -static int ov9740_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int ov9740_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  { -	a->c.left		= 0; -	a->c.top		= 0; -	a->c.width		= OV9740_MAX_WIDTH; -	a->c.height		= OV9740_MAX_HEIGHT; -	a->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +	case V4L2_SEL_TGT_CROP: +		sel->r.left = 0; +		sel->r.top = 0; +		sel->r.width = OV9740_MAX_WIDTH; +		sel->r.height = OV9740_MAX_HEIGHT; +		return 0; +	default: +		return -EINVAL; +	}  }  /* Set status of additional camera capabilities */ @@ -914,8 +910,6 @@ static int ov9740_g_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops ov9740_video_ops = {  	.s_stream	= ov9740_s_stream, -	.cropcap	= ov9740_cropcap, -	.g_crop		= ov9740_g_crop,  	.g_mbus_config	= ov9740_g_mbus_config,  }; @@ -929,6 +923,7 @@ static struct v4l2_subdev_core_ops ov9740_core_ops = {  static const struct v4l2_subdev_pad_ops ov9740_pad_ops = {  	.enum_mbus_code = ov9740_enum_mbus_code, +	.get_selection	= ov9740_get_selection,  	.set_fmt	= ov9740_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c index aa7bfbb4ad71..bc8ec59a3fbd 100644 --- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c +++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c @@ -538,15 +538,21 @@ static int rj54n1_commit(struct i2c_client *client)  static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h,  			       s32 *out_w, s32 *out_h); -static int rj54n1_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int rj54n1_set_selection(struct v4l2_subdev *sd, +				struct v4l2_subdev_pad_config *cfg, +				struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct rj54n1 *rj54n1 = to_rj54n1(client); -	const struct v4l2_rect *rect = &a->c; +	const struct v4l2_rect *rect = &sel->r;  	int dummy = 0, output_w, output_h,  		input_w = rect->width, input_h = rect->height;  	int ret; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP) +		return -EINVAL; +  	/* arbitrary minimum width and height, edges unimportant */  	soc_camera_limit_side(&dummy, &input_w,  		     RJ54N1_COLUMN_SKIP, 8, RJ54N1_MAX_WIDTH); @@ -573,29 +579,30 @@ static int rj54n1_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)  	return 0;  } -static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int rj54n1_get_selection(struct v4l2_subdev *sd, +				struct v4l2_subdev_pad_config *cfg, +				struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct rj54n1 *rj54n1 = to_rj54n1(client); -	a->c	= rj54n1->rect; -	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	a->bounds.left			= RJ54N1_COLUMN_SKIP; -	a->bounds.top			= RJ54N1_ROW_SKIP; -	a->bounds.width			= RJ54N1_MAX_WIDTH; -	a->bounds.height		= RJ54N1_MAX_HEIGHT; -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = RJ54N1_COLUMN_SKIP; +		sel->r.top = RJ54N1_ROW_SKIP; +		sel->r.width = RJ54N1_MAX_WIDTH; +		sel->r.height = RJ54N1_MAX_HEIGHT; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = rj54n1->rect; +		return 0; +	default: +		return -EINVAL; +	}  }  static int rj54n1_get_fmt(struct v4l2_subdev *sd, @@ -1246,15 +1253,14 @@ static int rj54n1_s_mbus_config(struct v4l2_subdev *sd,  static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {  	.s_stream	= rj54n1_s_stream, -	.g_crop		= rj54n1_g_crop, -	.s_crop		= rj54n1_s_crop, -	.cropcap	= rj54n1_cropcap,  	.g_mbus_config	= rj54n1_g_mbus_config,  	.s_mbus_config	= rj54n1_s_mbus_config,  };  static const struct v4l2_subdev_pad_ops rj54n1_subdev_pad_ops = {  	.enum_mbus_code = rj54n1_enum_mbus_code, +	.get_selection	= rj54n1_get_selection, +	.set_selection	= rj54n1_set_selection,  	.get_fmt	= rj54n1_get_fmt,  	.set_fmt	= rj54n1_set_fmt,  }; diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index 06aff81787a7..4002c07f3857 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c @@ -676,44 +676,28 @@ tw9910_set_fmt_error:  	return ret;  } -static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int tw9910_get_selection(struct v4l2_subdev *sd, +		struct v4l2_subdev_pad_config *cfg, +		struct v4l2_subdev_selection *sel)  {  	struct i2c_client *client = v4l2_get_subdevdata(sd);  	struct tw9910_priv *priv = to_tw9910(client); -	a->c.left	= 0; -	a->c.top	= 0; -	if (priv->norm & V4L2_STD_NTSC) { -		a->c.width	= 640; -		a->c.height	= 480; -	} else { -		a->c.width	= 768; -		a->c.height	= 576; -	} -	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -{ -	struct i2c_client *client = v4l2_get_subdevdata(sd); -	struct tw9910_priv *priv = to_tw9910(client); +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +		return -EINVAL; +	/* Only CROP, CROP_DEFAULT and CROP_BOUNDS are supported */ +	if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS) +		return -EINVAL; -	a->bounds.left			= 0; -	a->bounds.top			= 0; +	sel->r.left	= 0; +	sel->r.top	= 0;  	if (priv->norm & V4L2_STD_NTSC) { -		a->bounds.width		= 640; -		a->bounds.height	= 480; +		sel->r.width	= 640; +		sel->r.height	= 480;  	} else { -		a->bounds.width		= 768; -		a->bounds.height	= 576; +		sel->r.width	= 768; +		sel->r.height	= 576;  	} -	a->defrect			= a->bounds; -	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; -  	return 0;  } @@ -921,8 +905,6 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {  	.s_std		= tw9910_s_std,  	.g_std		= tw9910_g_std,  	.s_stream	= tw9910_s_stream, -	.cropcap	= tw9910_cropcap, -	.g_crop		= tw9910_g_crop,  	.g_mbus_config	= tw9910_g_mbus_config,  	.s_mbus_config	= tw9910_s_mbus_config,  	.g_tvnorms	= tw9910_g_tvnorms, @@ -930,6 +912,7 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {  static const struct v4l2_subdev_pad_ops tw9910_subdev_pad_ops = {  	.enum_mbus_code = tw9910_enum_mbus_code, +	.get_selection	= tw9910_get_selection,  	.get_fmt	= tw9910_get_fmt,  	.set_fmt	= tw9910_set_fmt,  }; diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index 73fc42bc2de6..42340e364cea 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c @@ -499,7 +499,6 @@ MODULE_DEVICE_TABLE(of, ths8200_of_match);  static struct i2c_driver ths8200_driver = {  	.driver = { -		.owner = THIS_MODULE,  		.name = "ths8200",  		.of_match_table = of_match_ptr(ths8200_of_match),  	}, diff --git a/drivers/media/i2c/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c index 0370dd89f1fc..2e06c06cac9b 100644 --- a/drivers/media/i2c/tlv320aic23b.c +++ b/drivers/media/i2c/tlv320aic23b.c @@ -210,7 +210,6 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id);  static struct i2c_driver tlv320aic23b_driver = {  	.driver = { -		.owner	= THIS_MODULE,  		.name	= "tlv320aic23b",  	},  	.probe		= tlv320aic23b_probe, diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 7cdd94842938..d5c9347f4c6d 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -977,7 +977,7 @@ static const struct v4l2_subdev_ops tvp514x_ops = {  	.pad = &tvp514x_pad_ops,  }; -static struct tvp514x_decoder tvp514x_dev = { +static const struct tvp514x_decoder tvp514x_dev = {  	.streaming = 0,  	.fmt_list = tvp514x_fmt_list,  	.num_fmts = ARRAY_SIZE(tvp514x_fmt_list), @@ -1233,7 +1233,6 @@ MODULE_DEVICE_TABLE(of, tvp514x_of_match);  static struct i2c_driver tvp514x_driver = {  	.driver = {  		.of_match_table = of_match_ptr(tvp514x_of_match), -		.owner = THIS_MODULE,  		.name = TVP514X_MODULE_NAME,  	},  	.probe = tvp514x_probe, diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 0b6d46c453bf..4740da39d698 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -871,19 +871,22 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,  	return 0;  } -static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) +static int tvp5150_set_selection(struct v4l2_subdev *sd, +				 struct v4l2_subdev_pad_config *cfg, +				 struct v4l2_subdev_selection *sel)  { -	struct v4l2_rect rect = a->c;  	struct tvp5150 *decoder = to_tvp5150(sd); +	struct v4l2_rect rect = sel->r;  	v4l2_std_id std; -	unsigned int hmax; +	int hmax; + +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +	    sel->target != V4L2_SEL_TGT_CROP) +		return -EINVAL;  	v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n",  		__func__, rect.left, rect.top, rect.width, rect.height); -	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -		return -EINVAL; -  	/* tvp5150 has some special limits */  	rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);  	rect.width = clamp_t(unsigned int, rect.width, @@ -924,44 +927,39 @@ static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)  	return 0;  } -static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) -{ -	struct tvp5150 *decoder = to_tvp5150(sd); - -	a->c	= decoder->rect; -	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; - -	return 0; -} - -static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +static int tvp5150_get_selection(struct v4l2_subdev *sd, +				 struct v4l2_subdev_pad_config *cfg, +				 struct v4l2_subdev_selection *sel)  { -	struct tvp5150 *decoder = to_tvp5150(sd); +	struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd);  	v4l2_std_id std; -	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)  		return -EINVAL; -	a->bounds.left			= 0; -	a->bounds.top			= 0; -	a->bounds.width			= TVP5150_H_MAX; - -	/* Calculate height based on current standard */ -	if (decoder->norm == V4L2_STD_ALL) -		std = tvp5150_read_std(sd); -	else -		std = decoder->norm; - -	if (std & V4L2_STD_525_60) -		a->bounds.height = TVP5150_V_MAX_525_60; -	else -		a->bounds.height = TVP5150_V_MAX_OTHERS; - -	a->defrect			= a->bounds; -	a->pixelaspect.numerator	= 1; -	a->pixelaspect.denominator	= 1; - -	return 0; +	switch (sel->target) { +	case V4L2_SEL_TGT_CROP_BOUNDS: +	case V4L2_SEL_TGT_CROP_DEFAULT: +		sel->r.left = 0; +		sel->r.top = 0; +		sel->r.width = TVP5150_H_MAX; + +		/* Calculate height based on current standard */ +		if (decoder->norm == V4L2_STD_ALL) +			std = tvp5150_read_std(sd); +		else +			std = decoder->norm; +		if (std & V4L2_STD_525_60) +			sel->r.height = TVP5150_V_MAX_525_60; +		else +			sel->r.height = TVP5150_V_MAX_OTHERS; +		return 0; +	case V4L2_SEL_TGT_CROP: +		sel->r = decoder->rect; +		return 0; +	default: +		return -EINVAL; +	}  }  static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, @@ -1173,7 +1171,7 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)  	return 0;  } -static int tvp5150_registered_async(struct v4l2_subdev *sd) +static int tvp5150_registered(struct v4l2_subdev *sd)  {  #ifdef CONFIG_MEDIA_CONTROLLER  	struct tvp5150 *decoder = to_tvp5150(sd); @@ -1222,7 +1220,6 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = {  	.g_register = tvp5150_g_register,  	.s_register = tvp5150_s_register,  #endif -	.registered_async = tvp5150_registered_async,  };  static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { @@ -1233,9 +1230,6 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = {  	.s_std = tvp5150_s_std,  	.s_stream = tvp5150_s_stream,  	.s_routing = tvp5150_s_routing, -	.s_crop = tvp5150_s_crop, -	.g_crop = tvp5150_g_crop, -	.cropcap = tvp5150_cropcap,  	.g_mbus_config = tvp5150_g_mbus_config,  }; @@ -1251,6 +1245,8 @@ static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {  	.enum_frame_size = tvp5150_enum_frame_size,  	.set_fmt = tvp5150_fill_fmt,  	.get_fmt = tvp5150_fill_fmt, +	.get_selection = tvp5150_get_selection, +	.set_selection = tvp5150_set_selection,  };  static const struct v4l2_subdev_ops tvp5150_ops = { @@ -1261,6 +1257,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {  	.pad = &tvp5150_pad_ops,  }; +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = { +	.registered = tvp5150_registered, +}; +  /****************************************************************************  			I2C Client & Driver @@ -1474,6 +1474,7 @@ static int tvp5150_probe(struct i2c_client *c,  	}  	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); +	sd->internal_ops = &tvp5150_internal_ops;  	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;  #if defined(CONFIG_MEDIA_CONTROLLER) diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 4df640c3aa40..3dc3341c4896 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -1086,7 +1086,6 @@ MODULE_DEVICE_TABLE(of, tvp7002_of_match);  static struct i2c_driver tvp7002_driver = {  	.driver = {  		.of_match_table = of_match_ptr(tvp7002_of_match), -		.owner = THIS_MODULE,  		.name = TVP7002_MODULE_NAME,  	},  	.probe = tvp7002_probe, diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c index 4c72a18c0b8c..be4cb7a8bdeb 100644 --- a/drivers/media/i2c/vs6624.c +++ b/drivers/media/i2c/vs6624.c @@ -863,7 +863,6 @@ MODULE_DEVICE_TABLE(i2c, vs6624_id);  static struct i2c_driver vs6624_driver = {  	.driver = { -		.owner  = THIS_MODULE,  		.name   = "vs6624",  	},  	.probe          = vs6624_probe, |