summaryrefslogtreecommitdiff
path: root/drivers/media/i2c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-26 03:55:48 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-26 03:55:48 +0300
commit5b4ca4447757019f11a601b0009534ef84bed801 (patch)
tree09bc8445e61aea621580d7587c21ac3f2b0cafb4 /drivers/media/i2c
parent0db9723cacf4d62bc3685fb15179b39ee4e17679 (diff)
parentfaebbd8f134f0c054f372982c8ddd1bbcc41b440 (diff)
downloadlinux-5b4ca4447757019f11a601b0009534ef84bed801.tar.xz
Merge tag 'media/v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - Lots of improvements at the DVB API DocBook documentation. Now, the frontend and the network APIs are fully in sync with the Kernel and looks more like the rest of the media documentation; - New frontend driver: cx24120 - New driver for a PCI device: cobalt. This driver is actually not sold in the market, but it is a good example of a multi-HDMI input device; - The dt3155 driver were promoted from staging; - The mantis driver got remote controller support; - New V4L2 driver for ST bdisp SoC chipsets; - Make sparse and smatch happier: several bugs were solved by fixing the issues reported by those static code analyzers. - Lots of new device additions, new features, improvements and cleanups at the existing drivers. * tag 'media/v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (553 commits) [media] lmedm04: fix the range for relative measurements [media] lmedm04: use u32 instead of u64 for relative stats [media] omap3isp: remove unused var [media] saa7134: fix page size on some archs [media] use CONFIG_PM_SLEEP for suspend/resume [media] tuner-i2c: be consistent with I2C declaration [media] si470x: cleanup define namespace [media] bdisp: prevent compiling on random arch [media] vb2: Don't WARN when v4l2_buffer.bytesused is 0 for multiplanar buffers [media] MAINTAINERS: Add entry for the Renesas VSP1 driver [media] videodev2.h: fix copy-and-paste error in V4L2_MAP_XFER_FUNC_DEFAULT [media] Revert "[media] vb2: Push mmap_sem down to memops" [media] mantis: cleanup a warning [media] bdisp-debug: don't try to divide by s64 [media] cx88: don't declare restart_video_queue if not used [media] au0828: move dev->boards atribuition to happen earlier [media] lmedm04: implement dvb v5 statistics [media] bdisp: remove unused var [media] bdisp: remove needless check ts2020: fix compilation on i386 ...
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r--drivers/media/i2c/Kconfig4
-rw-r--r--drivers/media/i2c/adp1653.c100
-rw-r--r--drivers/media/i2c/adv7170.c42
-rw-r--r--drivers/media/i2c/adv7175.c42
-rw-r--r--drivers/media/i2c/adv7183.c61
-rw-r--r--drivers/media/i2c/adv7511.c160
-rw-r--r--drivers/media/i2c/adv7604.c192
-rw-r--r--drivers/media/i2c/adv7842.c309
-rw-r--r--drivers/media/i2c/ak881x.c39
-rw-r--r--drivers/media/i2c/cx25840/cx25840-core.c17
-rw-r--r--drivers/media/i2c/ml86v7667.c29
-rw-r--r--drivers/media/i2c/mt9v011.c53
-rw-r--r--drivers/media/i2c/ov2659.c38
-rw-r--r--drivers/media/i2c/ov7670.c65
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c2
-rw-r--r--drivers/media/i2c/s5k5baf.c4
-rw-r--r--drivers/media/i2c/s5k6aa.c2
-rw-r--r--drivers/media/i2c/saa6752hs.c42
-rw-r--r--drivers/media/i2c/saa7115.c16
-rw-r--r--drivers/media/i2c/saa717x.c20
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c38
-rw-r--r--drivers/media/i2c/soc_camera/imx074.c66
-rw-r--r--drivers/media/i2c/soc_camera/mt9m001.c43
-rw-r--r--drivers/media/i2c/soc_camera/mt9m111.c57
-rw-r--r--drivers/media/i2c/soc_camera/mt9t031.c74
-rw-r--r--drivers/media/i2c/soc_camera/mt9t112.c41
-rw-r--r--drivers/media/i2c/soc_camera/mt9v022.c43
-rw-r--r--drivers/media/i2c/soc_camera/ov2640.c62
-rw-r--r--drivers/media/i2c/soc_camera/ov5642.c60
-rw-r--r--drivers/media/i2c/soc_camera/ov6650.c43
-rw-r--r--drivers/media/i2c/soc_camera/ov772x.c41
-rw-r--r--drivers/media/i2c/soc_camera/ov9640.c32
-rw-r--r--drivers/media/i2c/soc_camera/ov9740.c35
-rw-r--r--drivers/media/i2c/soc_camera/rj54n1cb0c.c66
-rw-r--r--drivers/media/i2c/soc_camera/tw9910.c41
-rw-r--r--drivers/media/i2c/sr030pc30.c62
-rw-r--r--drivers/media/i2c/tvaudio.c2
-rw-r--r--drivers/media/i2c/tvp514x.c55
-rw-r--r--drivers/media/i2c/tvp5150.c30
-rw-r--r--drivers/media/i2c/tvp7002.c48
-rw-r--r--drivers/media/i2c/vs6624.c55
41 files changed, 1484 insertions, 747 deletions
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 6f30ea76151a..71ee8f586430 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -196,7 +196,8 @@ config VIDEO_ADV7183
config VIDEO_ADV7604
tristate "Analog Devices ADV7604 decoder"
- depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && GPIOLIB
+ select HDMI
---help---
Support for the Analog Devices ADV7604 video decoder.
@@ -424,6 +425,7 @@ config VIDEO_ADV7393
config VIDEO_ADV7511
tristate "Analog Devices ADV7511 encoder"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+ select HDMI
---help---
Support for the Analog Devices ADV7511 video encoder.
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
index 873fe1949e98..c70ababce954 100644
--- a/drivers/media/i2c/adp1653.c
+++ b/drivers/media/i2c/adp1653.c
@@ -8,6 +8,7 @@
* Contributors:
* Sakari Ailus <sakari.ailus@iki.fi>
* Tuukka Toivonen <tuukkat76@gmail.com>
+ * Pavel Machek <pavel@ucw.cz>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -34,6 +35,8 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/gpio/consumer.h>
#include <media/adp1653.h>
#include <media/v4l2-device.h>
@@ -308,16 +311,28 @@ __adp1653_set_power(struct adp1653_flash *flash, int on)
{
int ret;
- ret = flash->platform_data->power(&flash->subdev, on);
- if (ret < 0)
- return ret;
+ if (flash->platform_data->power) {
+ ret = flash->platform_data->power(&flash->subdev, on);
+ if (ret < 0)
+ return ret;
+ } else {
+ gpiod_set_value(flash->platform_data->enable_gpio, on);
+ if (on)
+ /* Some delay is apparently required. */
+ udelay(20);
+ }
if (!on)
return 0;
ret = adp1653_init_device(flash);
- if (ret < 0)
+ if (ret >= 0)
+ return ret;
+
+ if (flash->platform_data->power)
flash->platform_data->power(&flash->subdev, 0);
+ else
+ gpiod_set_value(flash->platform_data->enable_gpio, 0);
return ret;
}
@@ -407,21 +422,85 @@ static int adp1653_resume(struct device *dev)
#endif /* CONFIG_PM */
+static int adp1653_of_init(struct i2c_client *client,
+ struct adp1653_flash *flash,
+ struct device_node *node)
+{
+ struct adp1653_platform_data *pd;
+ struct device_node *child;
+
+ pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+ flash->platform_data = pd;
+
+ child = of_get_child_by_name(node, "flash");
+ if (!child)
+ return -EINVAL;
+
+ if (of_property_read_u32(child, "flash-timeout-us",
+ &pd->max_flash_timeout))
+ goto err;
+
+ if (of_property_read_u32(child, "flash-max-microamp",
+ &pd->max_flash_intensity))
+ goto err;
+
+ pd->max_flash_intensity /= 1000;
+
+ if (of_property_read_u32(child, "led-max-microamp",
+ &pd->max_torch_intensity))
+ goto err;
+
+ pd->max_torch_intensity /= 1000;
+ of_node_put(child);
+
+ child = of_get_child_by_name(node, "indicator");
+ if (!child)
+ return -EINVAL;
+
+ if (of_property_read_u32(child, "led-max-microamp",
+ &pd->max_indicator_intensity))
+ goto err;
+
+ of_node_put(child);
+
+ pd->enable_gpio = devm_gpiod_get(&client->dev, "enable");
+ if (!pd->enable_gpio) {
+ dev_err(&client->dev, "Error getting GPIO\n");
+ return -EINVAL;
+ }
+
+ return 0;
+err:
+ dev_err(&client->dev, "Required property not found\n");
+ of_node_put(child);
+ return -EINVAL;
+}
+
+
static int adp1653_probe(struct i2c_client *client,
const struct i2c_device_id *devid)
{
struct adp1653_flash *flash;
int ret;
- /* we couldn't work without platform data */
- if (client->dev.platform_data == NULL)
- return -ENODEV;
-
flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
if (flash == NULL)
return -ENOMEM;
- flash->platform_data = client->dev.platform_data;
+ if (client->dev.of_node) {
+ ret = adp1653_of_init(client, flash, client->dev.of_node);
+ if (ret)
+ return ret;
+ } else {
+ if (!client->dev.platform_data) {
+ dev_err(&client->dev,
+ "Neither DT not platform data provided\n");
+ return EINVAL;
+ }
+ flash->platform_data = client->dev.platform_data;
+ }
mutex_init(&flash->power_lock);
@@ -442,6 +521,7 @@ static int adp1653_probe(struct i2c_client *client,
return 0;
free_and_quit:
+ dev_err(&client->dev, "adp1653: failed to register device\n");
v4l2_ctrl_handler_free(&flash->ctrls);
return ret;
}
@@ -464,7 +544,7 @@ static const struct i2c_device_id adp1653_id_table[] = {
};
MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
-static struct dev_pm_ops adp1653_pm_ops = {
+static const struct dev_pm_ops adp1653_pm_ops = {
.suspend = adp1653_suspend,
.resume = adp1653_resume,
};
diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c
index 40a1a95c7ce9..f0d3f5a2da46 100644
--- a/drivers/media/i2c/adv7170.c
+++ b/drivers/media/i2c/adv7170.c
@@ -262,21 +262,27 @@ static int adv7170_s_routing(struct v4l2_subdev *sd,
return 0;
}
-static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int adv7170_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(adv7170_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(adv7170_codes))
return -EINVAL;
- *code = adv7170_codes[index];
+ code->code = adv7170_codes[code->index];
return 0;
}
-static int adv7170_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int adv7170_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
u8 val = adv7170_read(sd, 0x7);
+ if (format->pad)
+ return -EINVAL;
+
if ((val & 0x40) == (1 << 6))
mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
else
@@ -290,11 +296,16 @@ static int adv7170_g_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int adv7170_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int adv7170_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
u8 val = adv7170_read(sd, 0x7);
- int ret;
+ int ret = 0;
+
+ if (format->pad)
+ return -EINVAL;
switch (mf->code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
@@ -311,7 +322,8 @@ static int adv7170_s_fmt(struct v4l2_subdev *sd,
return -EINVAL;
}
- ret = adv7170_write(sd, 0x7, val);
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ ret = adv7170_write(sd, 0x7, val);
return ret;
}
@@ -321,13 +333,17 @@ static int adv7170_s_fmt(struct v4l2_subdev *sd,
static const struct v4l2_subdev_video_ops adv7170_video_ops = {
.s_std_output = adv7170_s_std_output,
.s_routing = adv7170_s_routing,
- .s_mbus_fmt = adv7170_s_fmt,
- .g_mbus_fmt = adv7170_g_fmt,
- .enum_mbus_fmt = adv7170_enum_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops adv7170_pad_ops = {
+ .enum_mbus_code = adv7170_enum_mbus_code,
+ .get_fmt = adv7170_get_fmt,
+ .set_fmt = adv7170_set_fmt,
};
static const struct v4l2_subdev_ops adv7170_ops = {
.video = &adv7170_video_ops,
+ .pad = &adv7170_pad_ops,
};
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c
index d220af579a64..321834ba8f57 100644
--- a/drivers/media/i2c/adv7175.c
+++ b/drivers/media/i2c/adv7175.c
@@ -300,21 +300,27 @@ static int adv7175_s_routing(struct v4l2_subdev *sd,
return 0;
}
-static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int adv7175_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(adv7175_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(adv7175_codes))
return -EINVAL;
- *code = adv7175_codes[index];
+ code->code = adv7175_codes[code->index];
return 0;
}
-static int adv7175_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int adv7175_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
u8 val = adv7175_read(sd, 0x7);
+ if (format->pad)
+ return -EINVAL;
+
if ((val & 0x40) == (1 << 6))
mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
else
@@ -328,11 +334,16 @@ static int adv7175_g_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int adv7175_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int adv7175_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
u8 val = adv7175_read(sd, 0x7);
- int ret;
+ int ret = 0;
+
+ if (format->pad)
+ return -EINVAL;
switch (mf->code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
@@ -349,7 +360,8 @@ static int adv7175_s_fmt(struct v4l2_subdev *sd,
return -EINVAL;
}
- ret = adv7175_write(sd, 0x7, val);
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ ret = adv7175_write(sd, 0x7, val);
return ret;
}
@@ -374,14 +386,18 @@ static const struct v4l2_subdev_core_ops adv7175_core_ops = {
static const struct v4l2_subdev_video_ops adv7175_video_ops = {
.s_std_output = adv7175_s_std_output,
.s_routing = adv7175_s_routing,
- .s_mbus_fmt = adv7175_s_fmt,
- .g_mbus_fmt = adv7175_g_fmt,
- .enum_mbus_fmt = adv7175_enum_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops adv7175_pad_ops = {
+ .enum_mbus_code = adv7175_enum_mbus_code,
+ .get_fmt = adv7175_get_fmt,
+ .set_fmt = adv7175_set_fmt,
};
static const struct v4l2_subdev_ops adv7175_ops = {
.core = &adv7175_core_ops,
.video = &adv7175_video_ops,
+ .pad = &adv7175_pad_ops,
};
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
index 28940cc3a766..e2dd1617662f 100644
--- a/drivers/media/i2c/adv7183.c
+++ b/drivers/media/i2c/adv7183.c
@@ -420,20 +420,26 @@ static int adv7183_g_input_status(struct v4l2_subdev *sd, u32 *status)
return 0;
}
-static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int adv7183_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index > 0)
+ if (code->pad || code->index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
return 0;
}
-static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int adv7183_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct adv7183 *decoder = to_adv7183(sd);
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -446,25 +452,23 @@ static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd,
fmt->width = 720;
fmt->height = 576;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ decoder->fmt = *fmt;
+ else
+ cfg->try_fmt = *fmt;
return 0;
}
-static int adv7183_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int adv7183_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct adv7183 *decoder = to_adv7183(sd);
- adv7183_try_mbus_fmt(sd, fmt);
- decoder->fmt = *fmt;
- return 0;
-}
-
-static int adv7183_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
-{
- struct adv7183 *decoder = to_adv7183(sd);
+ if (format->pad)
+ return -EINVAL;
- *fmt = decoder->fmt;
+ format->format = decoder->fmt;
return 0;
}
@@ -514,16 +518,19 @@ static const struct v4l2_subdev_video_ops adv7183_video_ops = {
.s_routing = adv7183_s_routing,
.querystd = adv7183_querystd,
.g_input_status = adv7183_g_input_status,
- .enum_mbus_fmt = adv7183_enum_mbus_fmt,
- .try_mbus_fmt = adv7183_try_mbus_fmt,
- .s_mbus_fmt = adv7183_s_mbus_fmt,
- .g_mbus_fmt = adv7183_g_mbus_fmt,
.s_stream = adv7183_s_stream,
};
+static const struct v4l2_subdev_pad_ops adv7183_pad_ops = {
+ .enum_mbus_code = adv7183_enum_mbus_code,
+ .get_fmt = adv7183_get_fmt,
+ .set_fmt = adv7183_set_fmt,
+};
+
static const struct v4l2_subdev_ops adv7183_ops = {
.core = &adv7183_core_ops,
.video = &adv7183_video_ops,
+ .pad = &adv7183_pad_ops,
};
static int adv7183_probe(struct i2c_client *client,
@@ -533,7 +540,9 @@ static int adv7183_probe(struct i2c_client *client,
struct v4l2_subdev *sd;
struct v4l2_ctrl_handler *hdl;
int ret;
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
const unsigned *pin_array;
/* Check if the adapter supports the needed features */
@@ -603,9 +612,9 @@ static int adv7183_probe(struct i2c_client *client,
adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs));
adv7183_s_std(sd, decoder->std);
- fmt.width = 720;
- fmt.height = 576;
- adv7183_s_mbus_fmt(sd, &fmt);
+ fmt.format.width = 720;
+ fmt.format.height = 576;
+ adv7183_set_fmt(sd, NULL, &fmt);
/* initialize the hardware to the default control values */
ret = v4l2_ctrl_handler_setup(hdl);
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index 12d93203d405..95bcd4026451 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -77,7 +77,7 @@ struct adv7511_state_edid {
u32 blocks;
/* Number of segments read */
u32 segments;
- uint8_t data[EDID_MAX_SEGM * 256];
+ u8 data[EDID_MAX_SEGM * 256];
/* Number of EDID read retries left */
unsigned read_retries;
bool complete;
@@ -89,8 +89,9 @@ struct adv7511_state {
struct media_pad pad;
struct v4l2_ctrl_handler hdl;
int chip_revision;
- uint8_t i2c_edid_addr;
- uint8_t i2c_cec_addr;
+ u8 i2c_edid_addr;
+ u8 i2c_cec_addr;
+ u8 i2c_pktmem_addr;
/* Is the adv7511 powered on? */
bool power_on;
/* Did we receive hotplug and rx-sense signals? */
@@ -101,6 +102,7 @@ struct adv7511_state {
u32 colorspace;
u32 ycbcr_enc;
u32 quantization;
+ u32 xfer_func;
/* controls */
struct v4l2_ctrl *hdmi_mode_ctrl;
struct v4l2_ctrl *hotplug_ctrl;
@@ -108,6 +110,7 @@ struct adv7511_state {
struct v4l2_ctrl *have_edid0_ctrl;
struct v4l2_ctrl *rgb_quantization_range_ctrl;
struct i2c_client *i2c_edid;
+ struct i2c_client *i2c_pktmem;
struct adv7511_state_edid edid;
/* Running counter of the number of detected EDIDs (for debugging) */
unsigned edid_detect_counter;
@@ -200,7 +203,7 @@ static int adv7511_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
and then the value-mask (to be OR-ed). */
-static inline void adv7511_wr_and_or(struct v4l2_subdev *sd, u8 reg, uint8_t clr_mask, uint8_t val_mask)
+static inline void adv7511_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask)
{
adv7511_wr(sd, reg, (adv7511_rd(sd, reg) & clr_mask) | val_mask);
}
@@ -222,7 +225,7 @@ static int adv_smbus_read_i2c_block_data(struct i2c_client *client,
return ret;
}
-static inline void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t *buf)
+static inline void adv7511_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf)
{
struct adv7511_state *state = get_adv7511_state(sd);
int i;
@@ -237,6 +240,35 @@ static inline void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t
v4l2_err(sd, "%s: i2c read error\n", __func__);
}
+static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg)
+{
+ struct adv7511_state *state = get_adv7511_state(sd);
+
+ return adv_smbus_read_byte_data(state->i2c_pktmem, reg);
+}
+
+static int adv7511_pktmem_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+ struct adv7511_state *state = get_adv7511_state(sd);
+ int ret;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ ret = i2c_smbus_write_byte_data(state->i2c_pktmem, reg, val);
+ if (ret == 0)
+ return 0;
+ }
+ v4l2_err(sd, "%s: i2c write error\n", __func__);
+ return ret;
+}
+
+/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
+ and then the value-mask (to be OR-ed). */
+static inline void adv7511_pktmem_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask)
+{
+ adv7511_pktmem_wr(sd, reg, (adv7511_pktmem_rd(sd, reg) & clr_mask) | val_mask);
+}
+
static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd)
{
return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT;
@@ -247,7 +279,7 @@ static inline bool adv7511_have_rx_sense(struct v4l2_subdev *sd)
return adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT;
}
-static void adv7511_csc_conversion_mode(struct v4l2_subdev *sd, uint8_t mode)
+static void adv7511_csc_conversion_mode(struct v4l2_subdev *sd, u8 mode)
{
adv7511_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5);
}
@@ -291,7 +323,7 @@ static void adv7511_csc_coeff(struct v4l2_subdev *sd,
static void adv7511_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable)
{
if (enable) {
- uint8_t csc_mode = 0;
+ u8 csc_mode = 0;
adv7511_csc_conversion_mode(sd, csc_mode);
adv7511_csc_coeff(sd,
4096-564, 0, 0, 256,
@@ -414,6 +446,80 @@ static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi
}
#endif
+struct adv7511_cfg_read_infoframe {
+ const char *desc;
+ u8 present_reg;
+ u8 present_mask;
+ u8 header[3];
+ u16 payload_addr;
+};
+
+static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
+{
+ u8 csum = 0;
+ size_t i;
+
+ /* compute checksum */
+ for (i = 0; i < size; i++)
+ csum += ptr[i];
+
+ return 256 - csum;
+}
+
+static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_infoframe *cri)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct device *dev = &client->dev;
+ union hdmi_infoframe frame;
+ u8 buffer[32];
+ u8 len;
+ int i;
+
+ if (!(adv7511_rd(sd, cri->present_reg) & cri->present_mask)) {
+ v4l2_info(sd, "%s infoframe not transmitted\n", cri->desc);
+ return;
+ }
+
+ memcpy(buffer, cri->header, sizeof(cri->header));
+
+ len = buffer[2];
+
+ if (len + 4 > sizeof(buffer)) {
+ v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
+ return;
+ }
+
+ if (cri->payload_addr >= 0x100) {
+ for (i = 0; i < len; i++)
+ buffer[i + 4] = adv7511_pktmem_rd(sd, cri->payload_addr + i - 0x100);
+ } else {
+ for (i = 0; i < len; i++)
+ buffer[i + 4] = adv7511_rd(sd, cri->payload_addr + i);
+ }
+ buffer[3] = 0;
+ buffer[3] = hdmi_infoframe_checksum(buffer, len + 4);
+
+ if (hdmi_infoframe_unpack(&frame, buffer) < 0) {
+ v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
+ return;
+ }
+
+ hdmi_infoframe_log(KERN_INFO, dev, &frame);
+}
+
+static void adv7511_log_infoframes(struct v4l2_subdev *sd)
+{
+ static const struct adv7511_cfg_read_infoframe cri[] = {
+ { "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 },
+ { "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 },
+ { "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cri); i++)
+ log_infoframe(sd, &cri[i]);
+}
+
static int adv7511_log_status(struct v4l2_subdev *sd)
{
struct adv7511_state *state = get_adv7511_state(sd);
@@ -479,6 +585,7 @@ static int adv7511_log_status(struct v4l2_subdev *sd)
manual_cts ? "manual" : "automatic", N, CTS);
v4l2_info(sd, "VIC: detected %d, sent %d\n",
vic_detect, vic_sent);
+ adv7511_log_infoframes(sd);
}
if (state->dv_timings.type == V4L2_DV_BT_656_1120)
v4l2_print_dv_timings(sd->name, "timings: ",
@@ -487,6 +594,7 @@ static int adv7511_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "no timings set\n");
v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr);
v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr);
+ v4l2_info(sd, "i2c pktmem addr: 0x%x\n", state->i2c_pktmem_addr);
return 0;
}
@@ -536,6 +644,7 @@ static int adv7511_s_power(struct v4l2_subdev *sd, int on)
adv7511_wr(sd, 0xf9, 0x00);
adv7511_wr(sd, 0x43, state->i2c_edid_addr);
+ adv7511_wr(sd, 0x45, state->i2c_pktmem_addr);
/* Set number of attempts to read the EDID */
adv7511_wr(sd, 0xc9, 0xf);
@@ -545,8 +654,8 @@ static int adv7511_s_power(struct v4l2_subdev *sd, int on)
/* Enable interrupts */
static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
{
- uint8_t irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT;
- uint8_t irqs_rd;
+ u8 irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT;
+ u8 irqs_rd;
int retries = 100;
v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable");
@@ -579,7 +688,7 @@ static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
/* Interrupt handler */
static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
- uint8_t irq_status;
+ u8 irq_status;
/* disable interrupts to prevent a race condition */
adv7511_set_isr(sd, false);
@@ -861,11 +970,13 @@ static int adv7511_get_fmt(struct v4l2_subdev *sd,
format->format.colorspace = fmt->colorspace;
format->format.ycbcr_enc = fmt->ycbcr_enc;
format->format.quantization = fmt->quantization;
+ format->format.xfer_func = fmt->xfer_func;
} else {
format->format.code = state->fmt_code;
format->format.colorspace = state->colorspace;
format->format.ycbcr_enc = state->ycbcr_enc;
format->format.quantization = state->quantization;
+ format->format.xfer_func = state->xfer_func;
}
return 0;
@@ -912,6 +1023,7 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd,
fmt->colorspace = format->format.colorspace;
fmt->ycbcr_enc = format->format.ycbcr_enc;
fmt->quantization = format->format.quantization;
+ fmt->xfer_func = format->format.xfer_func;
return 0;
}
@@ -936,6 +1048,7 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd,
state->colorspace = format->format.colorspace;
state->ycbcr_enc = format->format.ycbcr_enc;
state->quantization = format->format.quantization;
+ state->xfer_func = format->format.xfer_func;
switch (format->format.colorspace) {
case V4L2_COLORSPACE_ADOBERGB:
@@ -1028,7 +1141,7 @@ static const struct v4l2_subdev_ops adv7511_ops = {
};
/* ----------------------------------------------------------------------- */
-static void adv7511_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, int segment, uint8_t *buf)
+static void adv7511_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, int segment, u8 *buf)
{
if (debug >= lvl) {
int i, j;
@@ -1140,7 +1253,7 @@ static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd)
{
struct adv7511_state *state = get_adv7511_state(sd);
/* read hotplug and rx-sense state */
- uint8_t status = adv7511_rd(sd, 0x42);
+ u8 status = adv7511_rd(sd, 0x42);
v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n",
__func__,
@@ -1184,9 +1297,9 @@ static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd)
}
}
-static bool edid_block_verify_crc(uint8_t *edid_block)
+static bool edid_block_verify_crc(u8 *edid_block)
{
- uint8_t sum = 0;
+ u8 sum = 0;
int i;
for (i = 0; i < 128; i++)
@@ -1198,7 +1311,7 @@ static bool edid_verify_crc(struct v4l2_subdev *sd, u32 segment)
{
struct adv7511_state *state = get_adv7511_state(sd);
u32 blocks = state->edid.blocks;
- uint8_t *data = state->edid.data;
+ u8 *data = state->edid.data;
if (!edid_block_verify_crc(&data[segment * 256]))
return false;
@@ -1223,7 +1336,7 @@ static bool edid_verify_header(struct v4l2_subdev *sd, u32 segment)
static bool adv7511_check_edid_status(struct v4l2_subdev *sd)
{
struct adv7511_state *state = get_adv7511_state(sd);
- uint8_t edidRdy = adv7511_rd(sd, 0xc5);
+ u8 edidRdy = adv7511_rd(sd, 0xc5);
v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n",
__func__, EDID_MAX_RETRIES - state->edid.read_retries);
@@ -1376,6 +1489,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
/* EDID and CEC i2c addr */
state->i2c_edid_addr = state->pdata.i2c_edid << 1;
state->i2c_cec_addr = state->pdata.i2c_cec << 1;
+ state->i2c_pktmem_addr = state->pdata.i2c_pktmem << 1;
state->chip_revision = adv7511_rd(sd, 0x0);
chip_id[0] = adv7511_rd(sd, 0xf5);
@@ -1393,12 +1507,19 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
goto err_entity;
}
+ state->i2c_pktmem = i2c_new_dummy(client->adapter, state->i2c_pktmem_addr >> 1);
+ if (state->i2c_pktmem == NULL) {
+ v4l2_err(sd, "failed to register pktmem i2c client\n");
+ err = -ENOMEM;
+ goto err_unreg_edid;
+ }
+
adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */
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_cec;
+ goto err_unreg_pktmem;
}
INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler);
@@ -1411,7 +1532,9 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
client->addr << 1, client->adapter->name);
return 0;
-err_unreg_cec:
+err_unreg_pktmem:
+ i2c_unregister_device(state->i2c_pktmem);
+err_unreg_edid:
i2c_unregister_device(state->i2c_edid);
err_entity:
media_entity_cleanup(&sd->entity);
@@ -1435,6 +1558,7 @@ static int adv7511_remove(struct i2c_client *client)
adv7511_init_setup(sd);
cancel_delayed_work(&state->edid_handler);
i2c_unregister_device(state->i2c_edid);
+ i2c_unregister_device(state->i2c_pktmem);
destroy_workqueue(state->work_queue);
v4l2_device_unregister_subdev(sd);
media_entity_cleanup(&sd->entity);
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 60ffcf098bef..808360fd6539 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -29,6 +29,7 @@
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
+#include <linux/hdmi.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -95,6 +96,13 @@ struct adv76xx_format_info {
u8 op_format_sel;
};
+struct adv76xx_cfg_read_infoframe {
+ const char *desc;
+ u8 present_mask;
+ u8 head_addr;
+ u8 payload_addr;
+};
+
struct adv76xx_chip_info {
enum adv76xx_type type;
@@ -124,6 +132,20 @@ struct adv76xx_chip_info {
unsigned int num_recommended_settings[2];
unsigned long page_mask;
+
+ /* Masks for timings */
+ unsigned int linewidth_mask;
+ unsigned int field0_height_mask;
+ unsigned int field1_height_mask;
+ unsigned int hfrontporch_mask;
+ unsigned int hsync_mask;
+ unsigned int hbackporch_mask;
+ unsigned int field0_vfrontporch_mask;
+ unsigned int field1_vfrontporch_mask;
+ unsigned int field0_vsync_mask;
+ unsigned int field1_vsync_mask;
+ unsigned int field0_vbackporch_mask;
+ unsigned int field1_vbackporch_mask;
};
/*
@@ -327,6 +349,11 @@ static const struct adv76xx_video_standards adv76xx_prim_mode_hdmi_gr[] = {
{ },
};
+static const struct v4l2_event adv76xx_ev_fmt = {
+ .type = V4L2_EVENT_SOURCE_CHANGE,
+ .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+};
+
/* ----------------------------------------------------------------------- */
static inline struct adv76xx_state *to_state(struct v4l2_subdev *sd)
@@ -1304,12 +1331,12 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
- timings))
+ false, timings))
return 0;
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
- state->aspect_ratio, timings))
+ false, state->aspect_ratio, timings))
return 0;
v4l2_dbg(2, debug, sd,
@@ -1504,23 +1531,28 @@ static int adv76xx_query_dv_timings(struct v4l2_subdev *sd,
if (is_digital_input(sd)) {
timings->type = V4L2_DV_BT_656_1120;
- /* FIXME: All masks are incorrect for ADV7611 */
- bt->width = hdmi_read16(sd, 0x07, 0xfff);
- bt->height = hdmi_read16(sd, 0x09, 0xfff);
+ bt->width = hdmi_read16(sd, 0x07, info->linewidth_mask);
+ bt->height = hdmi_read16(sd, 0x09, info->field0_height_mask);
bt->pixelclock = info->read_hdmi_pixelclock(sd);
- bt->hfrontporch = hdmi_read16(sd, 0x20, 0x3ff);
- bt->hsync = hdmi_read16(sd, 0x22, 0x3ff);
- bt->hbackporch = hdmi_read16(sd, 0x24, 0x3ff);
- bt->vfrontporch = hdmi_read16(sd, 0x2a, 0x1fff) / 2;
- bt->vsync = hdmi_read16(sd, 0x2e, 0x1fff) / 2;
- bt->vbackporch = hdmi_read16(sd, 0x32, 0x1fff) / 2;
+ bt->hfrontporch = hdmi_read16(sd, 0x20, info->hfrontporch_mask);
+ bt->hsync = hdmi_read16(sd, 0x22, info->hsync_mask);
+ bt->hbackporch = hdmi_read16(sd, 0x24, info->hbackporch_mask);
+ bt->vfrontporch = hdmi_read16(sd, 0x2a,
+ info->field0_vfrontporch_mask) / 2;
+ bt->vsync = hdmi_read16(sd, 0x2e, info->field0_vsync_mask) / 2;
+ bt->vbackporch = hdmi_read16(sd, 0x32,
+ info->field0_vbackporch_mask) / 2;
bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) |
((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0);
if (bt->interlaced == V4L2_DV_INTERLACED) {
- bt->height += hdmi_read16(sd, 0x0b, 0xfff);
- bt->il_vfrontporch = hdmi_read16(sd, 0x2c, 0x1fff) / 2;
- bt->il_vsync = hdmi_read16(sd, 0x30, 0x1fff) / 2;
- bt->il_vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2;
+ bt->height += hdmi_read16(sd, 0x0b,
+ info->field1_height_mask);
+ bt->il_vfrontporch = hdmi_read16(sd, 0x2c,
+ info->field1_vfrontporch_mask) / 2;
+ bt->il_vsync = hdmi_read16(sd, 0x30,
+ info->field1_vsync_mask) / 2;
+ bt->il_vbackporch = hdmi_read16(sd, 0x34,
+ info->field1_vbackporch_mask) / 2;
}
adv76xx_fill_optional_dv_timings_fields(sd, timings);
} else {
@@ -1725,11 +1757,11 @@ static int adv76xx_s_routing(struct v4l2_subdev *sd,
state->selected_input = input;
disable_input(sd);
-
select_input(sd);
-
enable_input(sd);
+ v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT,
+ (void *)&adv76xx_ev_fmt);
return 0;
}
@@ -1896,7 +1928,8 @@ static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
"%s: fmt_change = 0x%x, fmt_change_digital = 0x%x\n",
__func__, fmt_change, fmt_change_digital);
- v4l2_subdev_notify(sd, ADV76XX_FMT_CHANGE, NULL);
+ v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT,
+ (void *)&adv76xx_ev_fmt);
if (handled)
*handled = true;
@@ -2102,46 +2135,67 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
/*********** avi info frame CEA-861-E **************/
-static void print_avi_infoframe(struct v4l2_subdev *sd)
+static const struct adv76xx_cfg_read_infoframe adv76xx_cri[] = {
+ { "AVI", 0x01, 0xe0, 0x00 },
+ { "Audio", 0x02, 0xe3, 0x1c },
+ { "SDP", 0x04, 0xe6, 0x2a },
+ { "Vendor", 0x10, 0xec, 0x54 }
+};
+
+static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
+ union hdmi_infoframe *frame)
{
+ uint8_t buffer[32];
+ u8 len;
int i;
- u8 buf[14];
- u8 avi_len;
- u8 avi_ver;
- if (!is_hdmi(sd)) {
- v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n");
- return;
+ if (!(io_read(sd, 0x60) & adv76xx_cri[index].present_mask)) {
+ v4l2_info(sd, "%s infoframe not received\n",
+ adv76xx_cri[index].desc);
+ return -ENOENT;
}
- if (!(io_read(sd, 0x60) & 0x01)) {
- v4l2_info(sd, "AVI infoframe not received\n");
- return;
+
+ for (i = 0; i < 3; i++)
+ buffer[i] = infoframe_read(sd,
+ adv76xx_cri[index].head_addr + i);
+
+ len = buffer[2] + 1;
+
+ if (len + 3 > sizeof(buffer)) {
+ v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__,
+ adv76xx_cri[index].desc, len);
+ return -ENOENT;
}
- if (io_read(sd, 0x83) & 0x01) {
- v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n");
- io_write(sd, 0x85, 0x01); /* clear AVI_INF_CKS_ERR_RAW */
- if (io_read(sd, 0x83) & 0x01) {
- v4l2_info(sd, "AVI infoframe checksum error still present\n");
- io_write(sd, 0x85, 0x01); /* clear AVI_INF_CKS_ERR_RAW */
- }
+ for (i = 0; i < len; i++)
+ buffer[i + 3] = infoframe_read(sd,
+ adv76xx_cri[index].payload_addr + i);
+
+ if (hdmi_infoframe_unpack(frame, buffer) < 0) {
+ v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__,
+ adv76xx_cri[index].desc);
+ return -ENOENT;
}
+ return 0;
+}
- avi_len = infoframe_read(sd, 0xe2);
- avi_ver = infoframe_read(sd, 0xe1);
- v4l2_info(sd, "AVI infoframe version %d (%d byte)\n",
- avi_ver, avi_len);
+static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
+{
+ int i;
- if (avi_ver != 0x02)
+ if (!is_hdmi(sd)) {
+ v4l2_info(sd, "receive DVI-D signal, no infoframes\n");
return;
+ }
- for (i = 0; i < 14; i++)
- buf[i] = infoframe_read(sd, i);
+ for (i = 0; i < ARRAY_SIZE(adv76xx_cri); i++) {
+ union hdmi_infoframe frame;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
- v4l2_info(sd,
- "\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
- buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]);
+ if (adv76xx_read_infoframe(sd, i, &frame))
+ return;
+ hdmi_infoframe_log(KERN_INFO, &client->dev, &frame);
+ }
}
static int adv76xx_log_status(struct v4l2_subdev *sd)
@@ -2168,6 +2222,14 @@ static int adv76xx_log_status(struct v4l2_subdev *sd)
"invalid", "invalid", "invalid", "invalid", "invalid",
"invalid", "invalid", "automatic"
};
+ static const char * const hdmi_color_space_txt[16] = {
+ "RGB limited range (16-235)", "RGB full range (0-255)",
+ "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
+ "xvYCC Bt.601", "xvYCC Bt.709",
+ "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)",
+ "sYCC", "Adobe YCC 601", "AdobeRGB", "invalid", "invalid",
+ "invalid", "invalid", "invalid"
+ };
static const char * const rgb_quantization_range_txt[] = {
"Automatic",
"RGB limited range (16-235)",
@@ -2235,11 +2297,12 @@ static int adv76xx_log_status(struct v4l2_subdev *sd)
rgb_quantization_range_txt[state->rgb_quantization_range]);
v4l2_info(sd, "Input color space: %s\n",
input_color_space_txt[reg_io_0x02 >> 4]);
- v4l2_info(sd, "Output color space: %s %s, saturator %s\n",
+ v4l2_info(sd, "Output color space: %s %s, saturator %s, alt-gamma %s\n",
(reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
(reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)",
- ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ?
- "enabled" : "disabled");
+ (((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ?
+ "enabled" : "disabled",
+ (reg_io_0x02 & 0x08) ? "enabled" : "disabled");
v4l2_info(sd, "Color space conversion: %s\n",
csc_coeff_sel_rb[cp_read(sd, info->cp_csc) >> 4]);
@@ -2276,8 +2339,9 @@ static int adv76xx_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "AV Mute: %s\n", (hdmi_read(sd, 0x04) & 0x40) ? "on" : "off");
v4l2_info(sd, "Deep color mode: %s\n", deep_color_mode_txt[(hdmi_read(sd, 0x0b) & 0x60) >> 5]);
+ v4l2_info(sd, "HDMI colorspace: %s\n", hdmi_color_space_txt[hdmi_read(sd, 0x53) & 0xf]);
- print_avi_infoframe(sd);
+ adv76xx_log_infoframes(sd);
}
return 0;
@@ -2567,6 +2631,18 @@ static const struct adv76xx_chip_info adv76xx_chip_info[] = {
BIT(ADV76XX_PAGE_EDID) | BIT(ADV76XX_PAGE_HDMI) |
BIT(ADV76XX_PAGE_TEST) | BIT(ADV76XX_PAGE_CP) |
BIT(ADV7604_PAGE_VDP),
+ .linewidth_mask = 0xfff,
+ .field0_height_mask = 0xfff,
+ .field1_height_mask = 0xfff,
+ .hfrontporch_mask = 0x3ff,
+ .hsync_mask = 0x3ff,
+ .hbackporch_mask = 0x3ff,
+ .field0_vfrontporch_mask = 0x1fff,
+ .field0_vsync_mask = 0x1fff,
+ .field0_vbackporch_mask = 0x1fff,
+ .field1_vfrontporch_mask = 0x1fff,
+ .field1_vsync_mask = 0x1fff,
+ .field1_vbackporch_mask = 0x1fff,
},
[ADV7611] = {
.type = ADV7611,
@@ -2596,17 +2672,29 @@ static const struct adv76xx_chip_info adv76xx_chip_info[] = {
BIT(ADV76XX_PAGE_INFOFRAME) | BIT(ADV76XX_PAGE_AFE) |
BIT(ADV76XX_PAGE_REP) | BIT(ADV76XX_PAGE_EDID) |
BIT(ADV76XX_PAGE_HDMI) | BIT(ADV76XX_PAGE_CP),
+ .linewidth_mask = 0x1fff,
+ .field0_height_mask = 0x1fff,
+ .field1_height_mask = 0x1fff,
+ .hfrontporch_mask = 0x1fff,
+ .hsync_mask = 0x1fff,
+ .hbackporch_mask = 0x1fff,
+ .field0_vfrontporch_mask = 0x3fff,
+ .field0_vsync_mask = 0x3fff,
+ .field0_vbackporch_mask = 0x3fff,
+ .field1_vfrontporch_mask = 0x3fff,
+ .field1_vsync_mask = 0x3fff,
+ .field1_vbackporch_mask = 0x3fff,
},
};
-static struct i2c_device_id adv76xx_i2c_id[] = {
+static const struct i2c_device_id adv76xx_i2c_id[] = {
{ "adv7604", (kernel_ulong_t)&adv76xx_chip_info[ADV7604] },
{ "adv7611", (kernel_ulong_t)&adv76xx_chip_info[ADV7611] },
{ }
};
MODULE_DEVICE_TABLE(i2c, adv76xx_i2c_id);
-static struct of_device_id adv76xx_of_id[] __maybe_unused = {
+static const struct of_device_id adv76xx_of_id[] __maybe_unused = {
{ .compatible = "adi,adv7611", .data = &adv76xx_chip_info[ADV7611] },
{ }
};
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index b5a37fe10a6a..4cf79b2422d4 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -56,6 +56,28 @@ MODULE_LICENSE("GPL");
/* ADV7842 system clock frequency */
#define ADV7842_fsc (28636360)
+#define ADV7842_RGB_OUT (1 << 1)
+
+#define ADV7842_OP_FORMAT_SEL_8BIT (0 << 0)
+#define ADV7842_OP_FORMAT_SEL_10BIT (1 << 0)
+#define ADV7842_OP_FORMAT_SEL_12BIT (2 << 0)
+
+#define ADV7842_OP_MODE_SEL_SDR_422 (0 << 5)
+#define ADV7842_OP_MODE_SEL_DDR_422 (1 << 5)
+#define ADV7842_OP_MODE_SEL_SDR_444 (2 << 5)
+#define ADV7842_OP_MODE_SEL_DDR_444 (3 << 5)
+#define ADV7842_OP_MODE_SEL_SDR_422_2X (4 << 5)
+#define ADV7842_OP_MODE_SEL_ADI_CM (5 << 5)
+
+#define ADV7842_OP_CH_SEL_GBR (0 << 5)
+#define ADV7842_OP_CH_SEL_GRB (1 << 5)
+#define ADV7842_OP_CH_SEL_BGR (2 << 5)
+#define ADV7842_OP_CH_SEL_RGB (3 << 5)
+#define ADV7842_OP_CH_SEL_BRG (4 << 5)
+#define ADV7842_OP_CH_SEL_RBG (5 << 5)
+
+#define ADV7842_OP_SWAP_CB_CR (1 << 0)
+
/*
**********************************************************************
*
@@ -64,6 +86,14 @@ MODULE_LICENSE("GPL");
**********************************************************************
*/
+struct adv7842_format_info {
+ u32 code;
+ u8 op_ch_sel;
+ bool rgb_out;
+ bool swap_cb_cr;
+ u8 op_format_sel;
+};
+
struct adv7842_state {
struct adv7842_platform_data pdata;
struct v4l2_subdev sd;
@@ -72,6 +102,9 @@ struct adv7842_state {
enum adv7842_mode mode;
struct v4l2_dv_timings timings;
enum adv7842_vid_std_select vid_std_select;
+
+ const struct adv7842_format_info *format;
+
v4l2_std_id norm;
struct {
u8 edid[256];
@@ -209,6 +242,11 @@ static const struct adv7842_video_standards adv7842_prim_mode_hdmi_gr[] = {
{ },
};
+static const struct v4l2_event adv7842_ev_fmt = {
+ .type = V4L2_EVENT_SOURCE_CHANGE,
+ .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+};
+
/* ----------------------------------------------------------------------- */
static inline struct adv7842_state *to_state(struct v4l2_subdev *sd)
@@ -221,11 +259,21 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd;
}
+static inline unsigned hblanking(const struct v4l2_bt_timings *t)
+{
+ return V4L2_DV_BT_BLANKING_WIDTH(t);
+}
+
static inline unsigned htotal(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_FRAME_WIDTH(t);
}
+static inline unsigned vblanking(const struct v4l2_bt_timings *t)
+{
+ return V4L2_DV_BT_BLANKING_HEIGHT(t);
+}
+
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_FRAME_HEIGHT(t);
@@ -335,6 +383,12 @@ static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 va
return io_write(sd, reg, (io_read(sd, reg) & mask) | val);
}
+static inline int io_write_clr_set(struct v4l2_subdev *sd,
+ u8 reg, u8 mask, u8 val)
+{
+ return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
+}
+
static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7842_state *state = to_state(sd);
@@ -535,6 +589,64 @@ static void main_reset(struct v4l2_subdev *sd)
mdelay(5);
}
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+static const struct adv7842_format_info adv7842_formats[] = {
+ { MEDIA_BUS_FMT_RGB888_1X24, ADV7842_OP_CH_SEL_RGB, true, false,
+ ADV7842_OP_MODE_SEL_SDR_444 | ADV7842_OP_FORMAT_SEL_8BIT },
+ { MEDIA_BUS_FMT_YUYV8_2X8, ADV7842_OP_CH_SEL_RGB, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_8BIT },
+ { MEDIA_BUS_FMT_YVYU8_2X8, ADV7842_OP_CH_SEL_RGB, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_8BIT },
+ { MEDIA_BUS_FMT_YUYV10_2X10, ADV7842_OP_CH_SEL_RGB, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_10BIT },
+ { MEDIA_BUS_FMT_YVYU10_2X10, ADV7842_OP_CH_SEL_RGB, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_10BIT },
+ { MEDIA_BUS_FMT_YUYV12_2X12, ADV7842_OP_CH_SEL_RGB, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_12BIT },
+ { MEDIA_BUS_FMT_YVYU12_2X12, ADV7842_OP_CH_SEL_RGB, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_12BIT },
+ { MEDIA_BUS_FMT_UYVY8_1X16, ADV7842_OP_CH_SEL_RBG, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_8BIT },
+ { MEDIA_BUS_FMT_VYUY8_1X16, ADV7842_OP_CH_SEL_RBG, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_8BIT },
+ { MEDIA_BUS_FMT_YUYV8_1X16, ADV7842_OP_CH_SEL_RGB, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_8BIT },
+ { MEDIA_BUS_FMT_YVYU8_1X16, ADV7842_OP_CH_SEL_RGB, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_8BIT },
+ { MEDIA_BUS_FMT_UYVY10_1X20, ADV7842_OP_CH_SEL_RBG, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_10BIT },
+ { MEDIA_BUS_FMT_VYUY10_1X20, ADV7842_OP_CH_SEL_RBG, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_10BIT },
+ { MEDIA_BUS_FMT_YUYV10_1X20, ADV7842_OP_CH_SEL_RGB, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_10BIT },
+ { MEDIA_BUS_FMT_YVYU10_1X20, ADV7842_OP_CH_SEL_RGB, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_10BIT },
+ { MEDIA_BUS_FMT_UYVY12_1X24, ADV7842_OP_CH_SEL_RBG, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_12BIT },
+ { MEDIA_BUS_FMT_VYUY12_1X24, ADV7842_OP_CH_SEL_RBG, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_12BIT },
+ { MEDIA_BUS_FMT_YUYV12_1X24, ADV7842_OP_CH_SEL_RGB, false, false,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_12BIT },
+ { MEDIA_BUS_FMT_YVYU12_1X24, ADV7842_OP_CH_SEL_RGB, false, true,
+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_12BIT },
+};
+
+static const struct adv7842_format_info *
+adv7842_format_info(struct adv7842_state *state, u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(adv7842_formats); ++i) {
+ if (adv7842_formats[i].code == code)
+ return &adv7842_formats[i];
+ }
+
+ return NULL;
+}
+
/* ----------------------------------------------------------------------- */
static inline bool is_analog_input(struct v4l2_subdev *sd)
@@ -1333,12 +1445,12 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
- timings))
+ false, timings))
return 0;
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
- state->aspect_ratio, timings))
+ false, state->aspect_ratio, timings))
return 0;
v4l2_dbg(2, debug, sd,
@@ -1440,9 +1552,11 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
}
bt->interlaced = stdi.interlaced ?
V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+ bt->standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+ V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
if (is_digital_input(sd)) {
- uint32_t freq;
+ u32 freq;
timings->type = V4L2_DV_BT_656_1120;
@@ -1478,6 +1592,10 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
hdmi_read(sd, 0x31)) / 2;
bt->il_vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 +
hdmi_read(sd, 0x35)) / 2;
+ } else {
+ bt->il_vfrontporch = 0;
+ bt->il_vsync = 0;
+ bt->il_vbackporch = 0;
}
adv7842_fill_optional_dv_timings_fields(sd, timings);
} else {
@@ -1862,50 +1980,155 @@ static int adv7842_s_routing(struct v4l2_subdev *sd,
select_input(sd, state->vid_std_select);
enable_input(sd);
- v4l2_subdev_notify(sd, ADV7842_FMT_CHANGE, NULL);
+ v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT,
+ (void *)&adv7842_ev_fmt);
return 0;
}
-static int adv7842_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int adv7842_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index)
+ if (code->index >= ARRAY_SIZE(adv7842_formats))
return -EINVAL;
- /* Good enough for now */
- *code = MEDIA_BUS_FMT_FIXED;
+ code->code = adv7842_formats[code->index].code;
return 0;
}
-static int adv7842_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static void adv7842_fill_format(struct adv7842_state *state,
+ struct v4l2_mbus_framefmt *format)
+{
+ memset(format, 0, sizeof(*format));
+
+ format->width = state->timings.bt.width;
+ format->height = state->timings.bt.height;
+ format->field = V4L2_FIELD_NONE;
+ format->colorspace = V4L2_COLORSPACE_SRGB;
+
+ if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO)
+ format->colorspace = (state->timings.bt.height <= 576) ?
+ V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
+}
+
+/*
+ * Compute the op_ch_sel value required to obtain on the bus the component order
+ * corresponding to the selected format taking into account bus reordering
+ * applied by the board at the output of the device.
+ *
+ * The following table gives the op_ch_value from the format component order
+ * (expressed as op_ch_sel value in column) and the bus reordering (expressed as
+ * adv7842_bus_order value in row).
+ *
+ * | GBR(0) GRB(1) BGR(2) RGB(3) BRG(4) RBG(5)
+ * ----------+-------------------------------------------------
+ * RGB (NOP) | GBR GRB BGR RGB BRG RBG
+ * GRB (1-2) | BGR RGB GBR GRB RBG BRG
+ * RBG (2-3) | GRB GBR BRG RBG BGR RGB
+ * BGR (1-3) | RBG BRG RGB BGR GRB GBR
+ * BRG (ROR) | BRG RBG GRB GBR RGB BGR
+ * GBR (ROL) | RGB BGR RBG BRG GBR GRB
+ */
+static unsigned int adv7842_op_ch_sel(struct adv7842_state *state)
+{
+#define _SEL(a, b, c, d, e, f) { \
+ ADV7842_OP_CH_SEL_##a, ADV7842_OP_CH_SEL_##b, ADV7842_OP_CH_SEL_##c, \
+ ADV7842_OP_CH_SEL_##d, ADV7842_OP_CH_SEL_##e, ADV7842_OP_CH_SEL_##f }
+#define _BUS(x) [ADV7842_BUS_ORDER_##x]
+
+ static const unsigned int op_ch_sel[6][6] = {
+ _BUS(RGB) /* NOP */ = _SEL(GBR, GRB, BGR, RGB, BRG, RBG),
+ _BUS(GRB) /* 1-2 */ = _SEL(BGR, RGB, GBR, GRB, RBG, BRG),
+ _BUS(RBG) /* 2-3 */ = _SEL(GRB, GBR, BRG, RBG, BGR, RGB),
+ _BUS(BGR) /* 1-3 */ = _SEL(RBG, BRG, RGB, BGR, GRB, GBR),
+ _BUS(BRG) /* ROR */ = _SEL(BRG, RBG, GRB, GBR, RGB, BGR),
+ _BUS(GBR) /* ROL */ = _SEL(RGB, BGR, RBG, BRG, GBR, GRB),
+ };
+
+ return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel >> 5];
+}
+
+static void adv7842_setup_format(struct adv7842_state *state)
+{
+ struct v4l2_subdev *sd = &state->sd;
+
+ io_write_clr_set(sd, 0x02, 0x02,
+ state->format->rgb_out ? ADV7842_RGB_OUT : 0);
+ io_write(sd, 0x03, state->format->op_format_sel |
+ state->pdata.op_format_mode_sel);
+ io_write_clr_set(sd, 0x04, 0xe0, adv7842_op_ch_sel(state));
+ io_write_clr_set(sd, 0x05, 0x01,
+ state->format->swap_cb_cr ? ADV7842_OP_SWAP_CB_CR : 0);
+}
+
+static int adv7842_get_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct adv7842_state *state = to_state(sd);
- fmt->width = state->timings.bt.width;
- fmt->height = state->timings.bt.height;
- fmt->code = MEDIA_BUS_FMT_FIXED;
- fmt->field = V4L2_FIELD_NONE;
+ if (format->pad != ADV7842_PAD_SOURCE)
+ return -EINVAL;
if (state->mode == ADV7842_MODE_SDP) {
/* SPD block */
- if (!(sdp_read(sd, 0x5A) & 0x01))
+ if (!(sdp_read(sd, 0x5a) & 0x01))
return -EINVAL;
- fmt->width = 720;
+ format->format.code = MEDIA_BUS_FMT_YUYV8_2X8;
+ format->format.width = 720;
/* valid signal */
if (state->norm & V4L2_STD_525_60)
- fmt->height = 480;
+ format->format.height = 480;
else
- fmt->height = 576;
- fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ format->format.height = 576;
+ format->format.colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
}
- fmt->colorspace = V4L2_COLORSPACE_SRGB;
- if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
- fmt->colorspace = (state->timings.bt.height <= 576) ?
- V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
+ adv7842_fill_format(state, &format->format);
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *fmt;
+
+ fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
+ format->format.code = fmt->code;
+ } else {
+ format->format.code = state->format->code;
+ }
+
+ return 0;
+}
+
+static int adv7842_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct adv7842_state *state = to_state(sd);
+ const struct adv7842_format_info *info;
+
+ if (format->pad != ADV7842_PAD_SOURCE)
+ return -EINVAL;
+
+ if (state->mode == ADV7842_MODE_SDP)
+ return adv7842_get_format(sd, cfg, format);
+
+ info = adv7842_format_info(state, format->format.code);
+ if (info == NULL)
+ info = adv7842_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
+
+ adv7842_fill_format(state, &format->format);
+ format->format.code = info->code;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *fmt;
+
+ fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
+ fmt->code = format->format.code;
+ } else {
+ state->format = info;
+ adv7842_setup_format(state);
}
+
return 0;
}
@@ -1991,7 +2214,8 @@ static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
"%s: fmt_change_cp = 0x%x, fmt_change_digital = 0x%x, fmt_change_sdp = 0x%x\n",
__func__, fmt_change_cp, fmt_change_digital,
fmt_change_sdp);
- v4l2_subdev_notify(sd, ADV7842_FMT_CHANGE, NULL);
+ v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT,
+ (void *)&adv7842_ev_fmt);
if (handled)
*handled = true;
}
@@ -2110,7 +2334,7 @@ struct adv7842_cfg_read_infoframe {
static void log_infoframe(struct v4l2_subdev *sd, struct adv7842_cfg_read_infoframe *cri)
{
int i;
- uint8_t buffer[32];
+ u8 buffer[32];
union hdmi_infoframe frame;
u8 len;
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -2183,7 +2407,7 @@ static const char * const prim_mode_txt[] = {
static int adv7842_sdp_log_status(struct v4l2_subdev *sd)
{
/* SDP (Standard definition processor) block */
- uint8_t sdp_signal_detected = sdp_read(sd, 0x5A) & 0x01;
+ u8 sdp_signal_detected = sdp_read(sd, 0x5A) & 0x01;
v4l2_info(sd, "Chip powered %s\n", no_power(sd) ? "off" : "on");
v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n",
@@ -2227,10 +2451,10 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
/* CP block */
struct adv7842_state *state = to_state(sd);
struct v4l2_dv_timings timings;
- uint8_t reg_io_0x02 = io_read(sd, 0x02);
- uint8_t reg_io_0x21 = io_read(sd, 0x21);
- uint8_t reg_rep_0x77 = rep_read(sd, 0x77);
- uint8_t reg_rep_0x7d = rep_read(sd, 0x7d);
+ u8 reg_io_0x02 = io_read(sd, 0x02);
+ u8 reg_io_0x21 = io_read(sd, 0x21);
+ u8 reg_rep_0x77 = rep_read(sd, 0x77);
+ u8 reg_rep_0x7d = rep_read(sd, 0x7d);
bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01;
bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01;
bool audio_mute = io_read(sd, 0x65) & 0x40;
@@ -2302,10 +2526,10 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
if (no_cp_signal(sd)) {
v4l2_info(sd, "STDI: not locked\n");
} else {
- uint32_t bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2);
- uint32_t lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4);
- uint32_t lcvs = cp_read(sd, 0xb3) >> 3;
- uint32_t fcl = ((cp_read(sd, 0xb8) & 0x1f) << 8) | cp_read(sd, 0xb9);
+ u32 bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2);
+ u32 lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4);
+ u32 lcvs = cp_read(sd, 0xb3) >> 3;
+ u32 fcl = ((cp_read(sd, 0xb8) & 0x1f) << 8) | cp_read(sd, 0xb9);
char hs_pol = ((cp_read(sd, 0xb5) & 0x10) ?
((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x');
char vs_pol = ((cp_read(sd, 0xb5) & 0x40) ?
@@ -2545,14 +2769,11 @@ static int adv7842_core_init(struct v4l2_subdev *sd)
0xf0 |
pdata->alt_gamma << 3 |
pdata->op_656_range << 2 |
- pdata->rgb_out << 1 |
pdata->alt_data_sat << 0);
- io_write(sd, 0x03, pdata->op_format_sel);
- io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5);
io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 |
pdata->insert_av_codes << 2 |
- pdata->replicate_av_codes << 1 |
- pdata->invert_cbcr << 0);
+ pdata->replicate_av_codes << 1);
+ adv7842_setup_format(state);
/* HDMI audio */
hdmi_write_and_or(sd, 0x1a, 0xf1, 0x08); /* Wait 1 s before unmute */
@@ -2809,13 +3030,12 @@ static const struct v4l2_subdev_video_ops adv7842_video_ops = {
.s_dv_timings = adv7842_s_dv_timings,
.g_dv_timings = adv7842_g_dv_timings,
.query_dv_timings = adv7842_query_dv_timings,
- .enum_mbus_fmt = adv7842_enum_mbus_fmt,
- .g_mbus_fmt = adv7842_g_mbus_fmt,
- .try_mbus_fmt = adv7842_g_mbus_fmt,
- .s_mbus_fmt = adv7842_g_mbus_fmt,
};
static const struct v4l2_subdev_pad_ops adv7842_pad_ops = {
+ .enum_mbus_code = adv7842_enum_mbus_code,
+ .get_fmt = adv7842_get_format,
+ .set_fmt = adv7842_set_format,
.get_edid = adv7842_get_edid,
.set_edid = adv7842_set_edid,
.enum_dv_timings = adv7842_enum_dv_timings,
@@ -2986,6 +3206,7 @@ static int adv7842_probe(struct i2c_client *client,
/* platform data */
state->pdata = *pdata;
state->timings = cea640x480;
+ state->format = adv7842_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &adv7842_ops);
diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c
index 69aeaf397624..29846245aa3b 100644
--- a/drivers/media/i2c/ak881x.c
+++ b/drivers/media/i2c/ak881x.c
@@ -93,12 +93,17 @@ static int ak881x_s_register(struct v4l2_subdev *sd,
}
#endif
-static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ak881x_fill_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ak881x *ak881x = to_ak881x(client);
+ if (format->pad)
+ return -EINVAL;
+
v4l_bound_align_image(&mf->width, 0, 720, 2,
&mf->height, 0, ak881x->lines, 1, 0);
mf->field = V4L2_FIELD_INTERLACED;
@@ -108,23 +113,14 @@ static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ak881x_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (mf->field != V4L2_FIELD_INTERLACED ||
- mf->code != MEDIA_BUS_FMT_YUYV8_2X8)
+ if (code->pad || code->index)
return -EINVAL;
- return ak881x_try_g_mbus_fmt(sd, mf);
-}
-
-static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
-{
- if (index)
- return -EINVAL;
-
- *code = MEDIA_BUS_FMT_YUYV8_2X8;
+ code->code = MEDIA_BUS_FMT_YUYV8_2X8;
return 0;
}
@@ -211,18 +207,21 @@ static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = {
};
static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = {
- .s_mbus_fmt = ak881x_s_mbus_fmt,
- .g_mbus_fmt = ak881x_try_g_mbus_fmt,
- .try_mbus_fmt = ak881x_try_g_mbus_fmt,
.cropcap = ak881x_cropcap,
- .enum_mbus_fmt = ak881x_enum_mbus_fmt,
.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,
+ .set_fmt = ak881x_fill_fmt,
+ .get_fmt = ak881x_fill_fmt,
+};
+
static struct v4l2_subdev_ops ak881x_subdev_ops = {
.core = &ak881x_subdev_core_ops,
.video = &ak881x_subdev_video_ops,
+ .pad = &ak881x_subdev_pad_ops,
};
static int ak881x_probe(struct i2c_client *client,
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c
index bd496447749a..e15a789ad596 100644
--- a/drivers/media/i2c/cx25840/cx25840-core.c
+++ b/drivers/media/i2c/cx25840/cx25840-core.c
@@ -971,7 +971,7 @@ static void input_change(struct i2c_client *client)
not used by any public broadcast network, force
6.5 MHz carrier to be interpreted as System DK,
this avoids DK audio detection instability */
- cx25840_write(client, 0x80b, 0x00);
+ cx25840_write(client, 0x80b, 0x00);
} else if (std & V4L2_STD_SECAM) {
/* Autodetect audio standard and audio system */
cx25840_write(client, 0x808, 0xff);
@@ -1366,14 +1366,17 @@ static int cx25840_s_ctrl(struct v4l2_ctrl *ctrl)
/* ----------------------------------------------------------------------- */
-static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int cx25840_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
struct cx25840_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60);
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
@@ -1403,6 +1406,8 @@ static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt
fmt->width, fmt->height);
return -ERANGE;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
@@ -5068,7 +5073,6 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = {
.s_std = cx25840_s_std,
.g_std = cx25840_g_std,
.s_routing = cx25840_s_video_routing,
- .s_mbus_fmt = cx25840_s_mbus_fmt,
.s_stream = cx25840_s_stream,
.g_input_status = cx25840_g_input_status,
};
@@ -5080,12 +5084,17 @@ static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = {
.g_sliced_fmt = cx25840_g_sliced_fmt,
};
+static const struct v4l2_subdev_pad_ops cx25840_pad_ops = {
+ .set_fmt = cx25840_set_fmt,
+};
+
static const struct v4l2_subdev_ops cx25840_ops = {
.core = &cx25840_core_ops,
.tuner = &cx25840_tuner_ops,
.audio = &cx25840_audio_ops,
.video = &cx25840_video_ops,
.vbi = &cx25840_vbi_ops,
+ .pad = &cx25840_pad_ops,
.ir = &cx25840_ir_ops,
};
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c
index d7307862c2c5..af5eaf2db2a0 100644
--- a/drivers/media/i2c/ml86v7667.c
+++ b/drivers/media/i2c/ml86v7667.c
@@ -191,21 +191,27 @@ static int ml86v7667_g_input_status(struct v4l2_subdev *sd, u32 *status)
return 0;
}
-static int ml86v7667_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ml86v7667_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index > 0)
+ if (code->pad || code->index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV8_2X8;
+ code->code = MEDIA_BUS_FMT_YUYV8_2X8;
return 0;
}
-static int ml86v7667_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int ml86v7667_fill_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct ml86v7667_priv *priv = to_ml86v7667(sd);
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -279,13 +285,15 @@ static struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = {
.s_std = ml86v7667_s_std,
.querystd = ml86v7667_querystd,
.g_input_status = ml86v7667_g_input_status,
- .enum_mbus_fmt = ml86v7667_enum_mbus_fmt,
- .try_mbus_fmt = ml86v7667_mbus_fmt,
- .g_mbus_fmt = ml86v7667_mbus_fmt,
- .s_mbus_fmt = ml86v7667_mbus_fmt,
.g_mbus_config = ml86v7667_g_mbus_config,
};
+static const struct v4l2_subdev_pad_ops ml86v7667_subdev_pad_ops = {
+ .enum_mbus_code = ml86v7667_enum_mbus_code,
+ .get_fmt = ml86v7667_fill_fmt,
+ .set_fmt = ml86v7667_fill_fmt,
+};
+
static struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = {
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ml86v7667_g_register,
@@ -296,6 +304,7 @@ static struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = {
static struct v4l2_subdev_ops ml86v7667_subdev_ops = {
.core = &ml86v7667_subdev_core_ops,
.video = &ml86v7667_subdev_video_ops,
+ .pad = &ml86v7667_subdev_pad_ops,
};
static int ml86v7667_init(struct ml86v7667_priv *priv)
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
index a10f7f8f0558..57132cdba5ea 100644
--- a/drivers/media/i2c/mt9v011.c
+++ b/drivers/media/i2c/mt9v011.c
@@ -324,19 +324,25 @@ static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
return 0;
}
-static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int mt9v011_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index > 0)
+ if (code->pad || code->index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_SGRBG8_1X8;
+ code->code = MEDIA_BUS_FMT_SGRBG8_1X8;
return 0;
}
-static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int mt9v011_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
- if (fmt->code != MEDIA_BUS_FMT_SGRBG8_1X8)
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+ struct mt9v011 *core = to_mt9v011(sd);
+
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_SGRBG8_1X8)
return -EINVAL;
v4l_bound_align_image(&fmt->width, 48, 639, 1,
@@ -344,6 +350,15 @@ static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm
fmt->field = V4L2_FIELD_NONE;
fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ core->width = fmt->width;
+ core->height = fmt->height;
+
+ set_res(sd);
+ } else {
+ cfg->try_fmt = *fmt;
+ }
+
return 0;
}
@@ -385,23 +400,6 @@ static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
return 0;
}
-static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
-{
- struct mt9v011 *core = to_mt9v011(sd);
- int rc;
-
- rc = mt9v011_try_mbus_fmt(sd, fmt);
- if (rc < 0)
- return -EINVAL;
-
- core->width = fmt->width;
- core->height = fmt->height;
-
- set_res(sd);
-
- return 0;
-}
-
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9v011_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
@@ -469,16 +467,19 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
};
static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
- .enum_mbus_fmt = mt9v011_enum_mbus_fmt,
- .try_mbus_fmt = mt9v011_try_mbus_fmt,
- .s_mbus_fmt = mt9v011_s_mbus_fmt,
.g_parm = mt9v011_g_parm,
.s_parm = mt9v011_s_parm,
};
+static const struct v4l2_subdev_pad_ops mt9v011_pad_ops = {
+ .enum_mbus_code = mt9v011_enum_mbus_code,
+ .set_fmt = mt9v011_set_fmt,
+};
+
static const struct v4l2_subdev_ops mt9v011_ops = {
.core = &mt9v011_core_ops,
.video = &mt9v011_video_ops,
+ .pad = &mt9v011_pad_ops,
};
diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c
index edebd114279d..6edffc7b74e3 100644
--- a/drivers/media/i2c/ov2659.c
+++ b/drivers/media/i2c/ov2659.c
@@ -1046,16 +1046,21 @@ static int ov2659_get_fmt(struct v4l2_subdev *sd,
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2659 *ov2659 = to_ov2659(sd);
- struct v4l2_mbus_framefmt *mf;
dev_dbg(&client->dev, "ov2659_get_fmt\n");
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+ struct v4l2_mbus_framefmt *mf;
+
mf = v4l2_subdev_get_try_format(sd, cfg, 0);
mutex_lock(&ov2659->lock);
fmt->format = *mf;
mutex_unlock(&ov2659->lock);
return 0;
+#else
+ return -ENOTTY;
+#endif
}
mutex_lock(&ov2659->lock);
@@ -1102,7 +1107,7 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_format *fmt)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- unsigned int index = ARRAY_SIZE(ov2659_formats);
+ int index = ARRAY_SIZE(ov2659_formats);
struct v4l2_mbus_framefmt *mf = &fmt->format;
const struct ov2659_framesize *size = NULL;
struct ov2659 *ov2659 = to_ov2659(sd);
@@ -1126,8 +1131,12 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd,
mutex_lock(&ov2659->lock);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
*mf = fmt->format;
+#else
+ return -ENOTTY;
+#endif
} else {
s64 val;
@@ -1257,6 +1266,7 @@ static const char * const ov2659_test_pattern_menu[] = {
* V4L2 subdev internal operations
*/
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -1269,6 +1279,7 @@ static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
return 0;
}
+#endif
static const struct v4l2_subdev_core_ops ov2659_subdev_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
@@ -1287,6 +1298,7 @@ static const struct v4l2_subdev_pad_ops ov2659_subdev_pad_ops = {
.set_fmt = ov2659_set_fmt,
};
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
static const struct v4l2_subdev_ops ov2659_subdev_ops = {
.core = &ov2659_subdev_core_ops,
.video = &ov2659_subdev_video_ops,
@@ -1296,6 +1308,7 @@ static const struct v4l2_subdev_ops ov2659_subdev_ops = {
static const struct v4l2_subdev_internal_ops ov2659_subdev_internal_ops = {
.open = ov2659_open,
};
+#endif
static int ov2659_detect(struct v4l2_subdev *sd)
{
@@ -1340,8 +1353,8 @@ static struct ov2659_platform_data *
ov2659_get_pdata(struct i2c_client *client)
{
struct ov2659_platform_data *pdata;
+ struct v4l2_of_endpoint *bus_cfg;
struct device_node *endpoint;
- int ret;
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
return client->dev.platform_data;
@@ -1350,18 +1363,27 @@ ov2659_get_pdata(struct i2c_client *client)
if (!endpoint)
return NULL;
+ bus_cfg = v4l2_of_alloc_parse_endpoint(endpoint);
+ if (IS_ERR(bus_cfg)) {
+ pdata = NULL;
+ goto done;
+ }
+
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
goto done;
- ret = of_property_read_u64(endpoint, "link-frequencies",
- &pdata->link_frequency);
- if (ret) {
- dev_err(&client->dev, "link-frequencies property not found\n");
+ if (!bus_cfg->nr_of_link_frequencies) {
+ dev_err(&client->dev,
+ "link-frequencies property not found or too many\n");
pdata = NULL;
+ goto done;
}
+ pdata->link_frequency = bus_cfg->link_frequencies[0];
+
done:
+ v4l2_of_free_endpoint(bus_cfg);
of_node_put(endpoint);
return pdata;
}
@@ -1417,11 +1439,13 @@ static int ov2659_probe(struct i2c_client *client,
sd = &ov2659->sd;
client->flags |= I2C_CLIENT_SCCB;
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
v4l2_i2c_subdev_init(sd, client, &ov2659_subdev_ops);
sd->internal_ops = &ov2659_subdev_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
+#endif
#if defined(CONFIG_MEDIA_CONTROLLER)
ov2659->pad.flags = MEDIA_PAD_FL_SOURCE;
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index b9847527eb5a..2d1e25f10973 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -639,7 +639,7 @@ static struct ov7670_format_struct {
} ov7670_formats[] = {
{
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
- .colorspace = V4L2_COLORSPACE_JPEG,
+ .colorspace = V4L2_COLORSPACE_SRGB,
.regs = ov7670_fmt_yuv422,
.cmatrix = { 128, -128, 0, -34, -94, 128 },
},
@@ -899,13 +899,14 @@ static int ov7670_set_hw(struct v4l2_subdev *sd, int hstart, int hstop,
}
-static int ov7670_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int ov7670_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= N_OV7670_FMTS)
+ if (code->pad || code->index >= N_OV7670_FMTS)
return -EINVAL;
- *code = ov7670_formats[index].mbus_code;
+ code->code = ov7670_formats[code->index].mbus_code;
return 0;
}
@@ -970,17 +971,12 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
return 0;
}
-static int ov7670_try_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
-{
- return ov7670_try_fmt_internal(sd, fmt, NULL, NULL);
-}
-
/*
* Set a format.
*/
-static int ov7670_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int ov7670_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct ov7670_format_struct *ovfmt;
struct ov7670_win_size *wsize;
@@ -988,7 +984,18 @@ static int ov7670_s_mbus_fmt(struct v4l2_subdev *sd,
unsigned char com7;
int ret;
- ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
+ if (format->pad)
+ return -EINVAL;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL);
+ if (ret)
+ return ret;
+ cfg->try_fmt = format->format;
+ return 0;
+ }
+
+ ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize);
if (ret)
return ret;
@@ -1073,10 +1080,33 @@ static int ov7670_enum_frame_interval(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie)
{
+ struct ov7670_info *info = to_state(sd);
+ unsigned int n_win_sizes = info->devtype->n_win_sizes;
+ int i;
+
if (fie->pad)
return -EINVAL;
if (fie->index >= ARRAY_SIZE(ov7670_frame_rates))
return -EINVAL;
+
+ /*
+ * Check if the width/height is valid.
+ *
+ * If a minimum width/height was requested, filter out the capture
+ * windows that fall outside that.
+ */
+ for (i = 0; i < n_win_sizes; i++) {
+ struct ov7670_win_size *win = &info->devtype->win_sizes[i];
+
+ if (info->min_width && win->width < info->min_width)
+ continue;
+ if (info->min_height && win->height < info->min_height)
+ continue;
+ if (fie->width == win->width && fie->height == win->height)
+ break;
+ }
+ if (i == n_win_sizes)
+ return -EINVAL;
fie->interval.numerator = 1;
fie->interval.denominator = ov7670_frame_rates[fie->index];
return 0;
@@ -1362,7 +1392,7 @@ static int ov7670_s_exp(struct v4l2_subdev *sd, int value)
unsigned char com1, com8, aech, aechh;
ret = ov7670_read(sd, REG_COM1, &com1) +
- ov7670_read(sd, REG_COM8, &com8);
+ ov7670_read(sd, REG_COM8, &com8) +
ov7670_read(sd, REG_AECHH, &aechh);
if (ret)
return ret;
@@ -1485,9 +1515,6 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = {
};
static const struct v4l2_subdev_video_ops ov7670_video_ops = {
- .enum_mbus_fmt = ov7670_enum_mbus_fmt,
- .try_mbus_fmt = ov7670_try_mbus_fmt,
- .s_mbus_fmt = ov7670_s_mbus_fmt,
.s_parm = ov7670_s_parm,
.g_parm = ov7670_g_parm,
};
@@ -1495,6 +1522,8 @@ static const struct v4l2_subdev_video_ops ov7670_video_ops = {
static const struct v4l2_subdev_pad_ops ov7670_pad_ops = {
.enum_frame_interval = ov7670_enum_frame_interval,
.enum_frame_size = ov7670_enum_frame_size,
+ .enum_mbus_code = ov7670_enum_mbus_code,
+ .set_fmt = ov7670_set_fmt,
};
static const struct v4l2_subdev_ops ov7670_ops = {
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index 08b234bd2962..53c5ea89f0b9 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -1453,7 +1453,7 @@ static int s5c73m3_oif_set_power(struct v4l2_subdev *sd, int on)
state->apply_fiv = 1;
state->apply_fmt = 1;
}
- } else if (!on == state->power) {
+ } else if (state->power == !on) {
ret = s5c73m3_set_af_softlanding(state);
if (!ret)
ret = __s5c73m3_power_off(state);
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 297ef04e146a..774e0d0c94cb 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -491,7 +491,7 @@ static void s5k5baf_write_arr_seq(struct s5k5baf *state, u16 addr,
v4l2_dbg(3, debug, c, "i2c_write_seq(count=%d): %*ph\n", count,
min(2 * count, 64), seq);
- buf[0] = __constant_cpu_to_be16(REG_CMD_BUF);
+ buf[0] = cpu_to_be16(REG_CMD_BUF);
while (count > 0) {
int n = min_t(int, count, ARRAY_SIZE(buf) - 1);
@@ -1054,7 +1054,7 @@ static int s5k5baf_set_power(struct v4l2_subdev *sd, int on)
mutex_lock(&state->lock);
- if (!on != state->power)
+ if (state->power != !on)
goto out;
if (on) {
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c
index de803a11efb4..d0ad6a25bdab 100644
--- a/drivers/media/i2c/s5k6aa.c
+++ b/drivers/media/i2c/s5k6aa.c
@@ -875,7 +875,7 @@ static int s5k6aa_set_power(struct v4l2_subdev *sd, int on)
mutex_lock(&s5k6aa->lock);
- if (!on == s5k6aa->power) {
+ if (s5k6aa->power == !on) {
if (on) {
ret = __s5k6aa_power_on(s5k6aa);
if (!ret)
diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c
index f14c0e6435a3..ba3c4156644d 100644
--- a/drivers/media/i2c/saa6752hs.c
+++ b/drivers/media/i2c/saa6752hs.c
@@ -554,10 +554,16 @@ static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
return 0;
}
-static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+static int saa6752hs_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *f = &format->format;
struct saa6752hs_state *h = to_state(sd);
+ if (format->pad)
+ return -EINVAL;
+
if (h->video_format == SAA6752HS_VF_UNKNOWN)
h->video_format = SAA6752HS_VF_D1;
f->width = v4l2_format_table[h->video_format].fmt.pix.width;
@@ -568,10 +574,17 @@ static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm
return 0;
}
-static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+static int saa6752hs_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *f = &format->format;
+ struct saa6752hs_state *h = to_state(sd);
int dist_352, dist_480, dist_720;
+ if (format->pad)
+ return -EINVAL;
+
f->code = MEDIA_BUS_FMT_FIXED;
dist_352 = abs(f->width - 352);
@@ -592,15 +605,11 @@ static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_frame
}
f->field = V4L2_FIELD_INTERLACED;
f->colorspace = V4L2_COLORSPACE_SMPTE170M;
- return 0;
-}
-
-static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- struct saa6752hs_state *h = to_state(sd);
- if (f->code != MEDIA_BUS_FMT_FIXED)
- return -EINVAL;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *f;
+ return 0;
+ }
/*
FIXME: translate and round width/height into EMPRESS
@@ -614,7 +623,9 @@ static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm
D1 | 720x576 | 720x480
*/
- saa6752hs_try_mbus_fmt(sd, f);
+ if (f->code != MEDIA_BUS_FMT_FIXED)
+ return -EINVAL;
+
if (f->width == 720)
h->video_format = SAA6752HS_VF_D1;
else if (f->width == 480)
@@ -647,14 +658,17 @@ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
.s_std = saa6752hs_s_std,
- .s_mbus_fmt = saa6752hs_s_mbus_fmt,
- .try_mbus_fmt = saa6752hs_try_mbus_fmt,
- .g_mbus_fmt = saa6752hs_g_mbus_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops saa6752hs_pad_ops = {
+ .get_fmt = saa6752hs_get_fmt,
+ .set_fmt = saa6752hs_set_fmt,
};
static const struct v4l2_subdev_ops saa6752hs_ops = {
.core = &saa6752hs_core_ops,
.video = &saa6752hs_video_ops,
+ .pad = &saa6752hs_pad_ops,
};
static int saa6752hs_probe(struct i2c_client *client,
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index 7147c8b68fac..0eae5f4471e2 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -1170,12 +1170,18 @@ static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
return 0;
}
-static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int saa711x_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
return saa711x_set_size(sd, fmt->width, fmt->height);
}
@@ -1603,7 +1609,6 @@ static const struct v4l2_subdev_video_ops saa711x_video_ops = {
.s_std = saa711x_s_std,
.s_routing = saa711x_s_routing,
.s_crystal_freq = saa711x_s_crystal_freq,
- .s_mbus_fmt = saa711x_s_mbus_fmt,
.s_stream = saa711x_s_stream,
.querystd = saa711x_querystd,
.g_input_status = saa711x_g_input_status,
@@ -1617,12 +1622,17 @@ static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
.s_raw_fmt = saa711x_s_raw_fmt,
};
+static const struct v4l2_subdev_pad_ops saa711x_pad_ops = {
+ .set_fmt = saa711x_set_fmt,
+};
+
static const struct v4l2_subdev_ops saa711x_ops = {
.core = &saa711x_core_ops,
.tuner = &saa711x_tuner_ops,
.audio = &saa711x_audio_ops,
.video = &saa711x_video_ops,
.vbi = &saa711x_vbi_ops,
+ .pad = &saa711x_pad_ops,
};
#define CHIP_VER_SIZE 16
diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c
index 0d0f9a917cd3..7d517361e419 100644
--- a/drivers/media/i2c/saa717x.c
+++ b/drivers/media/i2c/saa717x.c
@@ -152,9 +152,9 @@ static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
i2c_transfer(adap, msgs, 2);
if (fw_addr)
- value = (mm2[2] & 0xff) | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
+ value = (mm2[2] << 16) | (mm2[1] << 8) | mm2[0];
else
- value = mm2[0] & 0xff;
+ value = mm2[0];
v4l2_dbg(2, debug, sd, "read: reg 0x%03x=0x%08x\n", reg, value);
return value;
@@ -992,13 +992,16 @@ static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi
}
#endif
-static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int saa717x_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
int prescale, h_scale, v_scale;
v4l2_dbg(1, debug, sd, "decoder set size\n");
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
return -EINVAL;
/* FIXME need better bounds checking here */
@@ -1010,6 +1013,9 @@ static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt
fmt->field = V4L2_FIELD_INTERLACED;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
/* scaling setting */
/* NTSC and interlace only */
prescale = SAA717X_NTSC_WIDTH / fmt->width;
@@ -1217,7 +1223,6 @@ static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
static const struct v4l2_subdev_video_ops saa717x_video_ops = {
.s_std = saa717x_s_std,
.s_routing = saa717x_s_video_routing,
- .s_mbus_fmt = saa717x_s_mbus_fmt,
.s_stream = saa717x_s_stream,
};
@@ -1225,11 +1230,16 @@ static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
.s_routing = saa717x_s_audio_routing,
};
+static const struct v4l2_subdev_pad_ops saa717x_pad_ops = {
+ .set_fmt = saa717x_set_fmt,
+};
+
static const struct v4l2_subdev_ops saa717x_ops = {
.core = &saa717x_core_ops,
.tuner = &saa717x_tuner_ops,
.audio = &saa717x_audio_ops,
.video = &saa717x_video_ops,
+ .pad = &saa717x_pad_ops,
};
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 557f25def3a0..636ebd6fe5dc 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2975,9 +2975,9 @@ static int smiapp_resume(struct device *dev)
static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
{
struct smiapp_platform_data *pdata;
- struct v4l2_of_endpoint bus_cfg;
+ struct v4l2_of_endpoint *bus_cfg;
struct device_node *ep;
- uint32_t asize;
+ int i;
int rval;
if (!dev->of_node)
@@ -2987,13 +2987,15 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
if (!ep)
return NULL;
+ bus_cfg = v4l2_of_alloc_parse_endpoint(ep);
+ if (IS_ERR(bus_cfg))
+ goto out_err;
+
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
goto out_err;
- v4l2_of_parse_endpoint(ep, &bus_cfg);
-
- switch (bus_cfg.bus_type) {
+ switch (bus_cfg->bus_type) {
case V4L2_MBUS_CSI2:
pdata->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2;
break;
@@ -3002,7 +3004,7 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
goto out_err;
}
- pdata->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
+ pdata->lanes = bus_cfg->bus.mipi_csi2.num_data_lanes;
dev_dbg(dev, "lanes %u\n", pdata->lanes);
/* xshutdown GPIO is optional */
@@ -3022,34 +3024,30 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
dev_dbg(dev, "reset %d, nvm %d, clk %d, csi %d\n", pdata->xshutdown,
pdata->nvm_size, pdata->ext_clk, pdata->csi_signalling_mode);
- rval = of_get_property(ep, "link-frequencies", &asize) ? 0 : -ENOENT;
- if (rval) {
- dev_warn(dev, "can't get link-frequencies array size\n");
+ if (!bus_cfg->nr_of_link_frequencies) {
+ dev_warn(dev, "no link frequencies defined\n");
goto out_err;
}
- pdata->op_sys_clock = devm_kzalloc(dev, asize, GFP_KERNEL);
+ pdata->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) {
rval = -ENOMEM;
goto out_err;
}
- asize /= sizeof(*pdata->op_sys_clock);
- rval = of_property_read_u64_array(
- ep, "link-frequencies", pdata->op_sys_clock, asize);
- if (rval) {
- dev_warn(dev, "can't get link-frequencies\n");
- 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]);
}
- for (; asize > 0; asize--)
- dev_dbg(dev, "freq %d: %lld\n", asize - 1,
- pdata->op_sys_clock[asize - 1]);
-
+ v4l2_of_free_endpoint(bus_cfg);
of_node_put(ep);
return pdata;
out_err:
+ v4l2_of_free_endpoint(bus_cfg);
of_node_put(ep);
return NULL;
}
diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c
index ec89cfa927a2..f68c2352c63c 100644
--- a/drivers/media/i2c/soc_camera/imx074.c
+++ b/drivers/media/i2c/soc_camera/imx074.c
@@ -153,14 +153,24 @@ static int reg_read(struct i2c_client *client, const u16 addr)
return buf[0] & 0xff; /* no sign-extension */
}
-static int imx074_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int imx074_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
const struct imx074_datafmt *fmt = imx074_find_datafmt(mf->code);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct imx074 *priv = to_imx074(client);
+
+ if (format->pad)
+ return -EINVAL;
dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
if (!fmt) {
+ /* MIPI CSI could have changed the format, double-check */
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
mf->code = imx074_colour_fmts[0].code;
mf->colorspace = imx074_colour_fmts[0].colorspace;
}
@@ -169,36 +179,27 @@ static int imx074_try_fmt(struct v4l2_subdev *sd,
mf->height = IMX074_HEIGHT;
mf->field = V4L2_FIELD_NONE;
- return 0;
-}
-
-static int imx074_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct imx074 *priv = to_imx074(client);
-
- dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
-
- /* MIPI CSI could have changed the format, double-check */
- if (!imx074_find_datafmt(mf->code))
- return -EINVAL;
-
- imx074_try_fmt(sd, mf);
-
- priv->fmt = imx074_find_datafmt(mf->code);
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ priv->fmt = imx074_find_datafmt(mf->code);
+ else
+ cfg->try_fmt = *mf;
return 0;
}
-static int imx074_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int imx074_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct imx074 *priv = to_imx074(client);
const struct imx074_datafmt *fmt = priv->fmt;
+ if (format->pad)
+ return -EINVAL;
+
mf->code = fmt->code;
mf->colorspace = fmt->colorspace;
mf->width = IMX074_WIDTH;
@@ -235,13 +236,15 @@ static int imx074_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int imx074_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int imx074_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if ((unsigned int)index >= ARRAY_SIZE(imx074_colour_fmts))
+ if (code->pad ||
+ (unsigned int)code->index >= ARRAY_SIZE(imx074_colour_fmts))
return -EINVAL;
- *code = imx074_colour_fmts[index].code;
+ code->code = imx074_colour_fmts[code->index].code;
return 0;
}
@@ -275,10 +278,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,
- .s_mbus_fmt = imx074_s_fmt,
- .g_mbus_fmt = imx074_g_fmt,
- .try_mbus_fmt = imx074_try_fmt,
- .enum_mbus_fmt = imx074_enum_fmt,
.g_crop = imx074_g_crop,
.cropcap = imx074_cropcap,
.g_mbus_config = imx074_g_mbus_config,
@@ -288,9 +287,16 @@ static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
.s_power = imx074_s_power,
};
+static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = {
+ .enum_mbus_code = imx074_enum_mbus_code,
+ .get_fmt = imx074_get_fmt,
+ .set_fmt = imx074_set_fmt,
+};
+
static struct v4l2_subdev_ops imx074_subdev_ops = {
.core = &imx074_subdev_core_ops,
.video = &imx074_subdev_video_ops,
+ .pad = &imx074_subdev_pad_ops,
};
static int imx074_video_probe(struct i2c_client *client)
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
index 2e9a53502551..4fbdd1e9f7ee 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -205,7 +205,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
/*
* The caller provides a supported format, as verified per
- * call to .try_mbus_fmt()
+ * call to .set_fmt(FORMAT_TRY).
*/
if (!ret)
ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
@@ -250,11 +250,16 @@ static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int mt9m001_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9m001_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m001 *mt9m001 = to_mt9m001(client);
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
mf->width = mt9m001->rect.width;
mf->height = mt9m001->rect.height;
@@ -293,13 +298,18 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd,
return ret;
}
-static int mt9m001_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9m001_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m001 *mt9m001 = to_mt9m001(client);
const struct mt9m001_datafmt *fmt;
+ if (format->pad)
+ return -EINVAL;
+
v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH,
MT9M001_MAX_WIDTH, 1,
&mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top,
@@ -317,6 +327,9 @@ static int mt9m001_try_fmt(struct v4l2_subdev *sd,
mf->colorspace = fmt->colorspace;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return mt9m001_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
@@ -562,16 +575,17 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
.s_power = mt9m001_s_power,
};
-static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9m001_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m001 *mt9m001 = to_mt9m001(client);
- if (index >= mt9m001->num_fmts)
+ if (code->pad || code->index >= mt9m001->num_fmts)
return -EINVAL;
- *code = mt9m001->fmts[index].code;
+ code->code = mt9m001->fmts[code->index].code;
return 0;
}
@@ -611,13 +625,9 @@ 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_mbus_fmt = mt9m001_s_fmt,
- .g_mbus_fmt = mt9m001_g_fmt,
- .try_mbus_fmt = mt9m001_try_fmt,
.s_crop = mt9m001_s_crop,
.g_crop = mt9m001_g_crop,
.cropcap = mt9m001_cropcap,
- .enum_mbus_fmt = mt9m001_enum_fmt,
.g_mbus_config = mt9m001_g_mbus_config,
.s_mbus_config = mt9m001_s_mbus_config,
};
@@ -626,10 +636,17 @@ static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
.g_skip_top_lines = mt9m001_g_skip_top_lines,
};
+static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = {
+ .enum_mbus_code = mt9m001_enum_mbus_code,
+ .get_fmt = mt9m001_get_fmt,
+ .set_fmt = mt9m001_set_fmt,
+};
+
static struct v4l2_subdev_ops mt9m001_subdev_ops = {
.core = &mt9m001_subdev_core_ops,
.video = &mt9m001_subdev_video_ops,
.sensor = &mt9m001_subdev_sensor_ops,
+ .pad = &mt9m001_subdev_pad_ops,
};
static int mt9m001_probe(struct i2c_client *client,
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c
index 441e0fda24fe..6dfaead6aaa8 100644
--- a/drivers/media/i2c/soc_camera/mt9m111.c
+++ b/drivers/media/i2c/soc_camera/mt9m111.c
@@ -447,11 +447,16 @@ static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int mt9m111_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9m111_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = mt9m111->width;
mf->height = mt9m111->height;
mf->code = mt9m111->fmt->code;
@@ -531,14 +536,20 @@ static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
return ret;
}
-static int mt9m111_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9m111_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
const struct mt9m111_datafmt *fmt;
struct v4l2_rect *rect = &mt9m111->rect;
bool bayer;
+ int ret;
+
+ if (format->pad)
+ return -EINVAL;
fmt = mt9m111_find_datafmt(mt9m111, mf->code);
@@ -572,20 +583,10 @@ static int mt9m111_try_fmt(struct v4l2_subdev *sd,
mf->code = fmt->code;
mf->colorspace = fmt->colorspace;
- return 0;
-}
-
-static int mt9m111_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- const struct mt9m111_datafmt *fmt;
- struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
- struct v4l2_rect *rect = &mt9m111->rect;
- int ret;
-
- mt9m111_try_fmt(sd, mf);
- fmt = mt9m111_find_datafmt(mt9m111, mf->code);
- /* try_fmt() guarantees fmt != NULL && fmt->code == mf->code */
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
ret = mt9m111_setup_geometry(mt9m111, rect, mf->width, mf->height, mf->code);
if (!ret)
@@ -839,13 +840,14 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
#endif
};
-static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9m111_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
+ if (code->pad || code->index >= ARRAY_SIZE(mt9m111_colour_fmts))
return -EINVAL;
- *code = mt9m111_colour_fmts[index].code;
+ code->code = mt9m111_colour_fmts[code->index].code;
return 0;
}
@@ -865,19 +867,22 @@ static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
}
static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
- .s_mbus_fmt = mt9m111_s_fmt,
- .g_mbus_fmt = mt9m111_g_fmt,
- .try_mbus_fmt = mt9m111_try_fmt,
.s_crop = mt9m111_s_crop,
.g_crop = mt9m111_g_crop,
.cropcap = mt9m111_cropcap,
- .enum_mbus_fmt = mt9m111_enum_fmt,
.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_fmt = mt9m111_get_fmt,
+ .set_fmt = mt9m111_set_fmt,
+};
+
static struct v4l2_subdev_ops mt9m111_subdev_ops = {
.core = &mt9m111_subdev_core_ops,
.video = &mt9m111_subdev_video_ops,
+ .pad = &mt9m111_subdev_pad_ops,
};
/*
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
index 35d9c8d25589..3b6eeed2e2b9 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
- * .try_mbus_fmt(), soc_camera_s_crop() and soc_camera_cropcap()
+ * .set_fmt(FORMAT_TRY), soc_camera_s_crop() and soc_camera_cropcap()
*/
if (ret >= 0)
ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
@@ -337,12 +337,17 @@ static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int mt9t031_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9t031_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t031 *mt9t031 = to_mt9t031(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = mt9t031->rect.width / mt9t031->xskip;
mf->height = mt9t031->rect.height / mt9t031->yskip;
mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
@@ -352,16 +357,36 @@ static int mt9t031_g_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int mt9t031_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+/*
+ * If a user window larger than sensor window is requested, we'll increase the
+ * sensor window.
+ */
+static int mt9t031_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t031 *mt9t031 = to_mt9t031(client);
u16 xskip, yskip;
struct v4l2_rect rect = mt9t031->rect;
+ if (format->pad)
+ return -EINVAL;
+
+ mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ mf->colorspace = V4L2_COLORSPACE_SRGB;
+ v4l_bound_align_image(
+ &mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
+ &mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
+
/*
- * try_fmt has put width and height within limits.
+ * Width and height are within limits.
* S_FMT: use binning and skipping for scaling
*/
xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH);
@@ -374,23 +399,6 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd,
return mt9t031_set_params(client, &rect, xskip, yskip);
}
-/*
- * If a user window larger than sensor window is requested, we'll increase the
- * sensor window.
- */
-static int mt9t031_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- v4l_bound_align_image(
- &mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
- &mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
-
- mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
- mf->colorspace = V4L2_COLORSPACE_SRGB;
-
- return 0;
-}
-
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9t031_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
@@ -672,13 +680,14 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
#endif
};
-static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9t031_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index)
+ if (code->pad || code->index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
return 0;
}
@@ -712,13 +721,9 @@ 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_mbus_fmt = mt9t031_s_fmt,
- .g_mbus_fmt = mt9t031_g_fmt,
- .try_mbus_fmt = mt9t031_try_fmt,
.s_crop = mt9t031_s_crop,
.g_crop = mt9t031_g_crop,
.cropcap = mt9t031_cropcap,
- .enum_mbus_fmt = mt9t031_enum_fmt,
.g_mbus_config = mt9t031_g_mbus_config,
.s_mbus_config = mt9t031_s_mbus_config,
};
@@ -727,10 +732,17 @@ static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = {
.g_skip_top_lines = mt9t031_g_skip_top_lines,
};
+static const struct v4l2_subdev_pad_ops mt9t031_subdev_pad_ops = {
+ .enum_mbus_code = mt9t031_enum_mbus_code,
+ .get_fmt = mt9t031_get_fmt,
+ .set_fmt = mt9t031_set_fmt,
+};
+
static struct v4l2_subdev_ops mt9t031_subdev_ops = {
.core = &mt9t031_subdev_core_ops,
.video = &mt9t031_subdev_video_ops,
.sensor = &mt9t031_subdev_sensor_ops,
+ .pad = &mt9t031_subdev_pad_ops,
};
static int mt9t031_probe(struct i2c_client *client,
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
index 64f08365e6b2..de10a76ba6df 100644
--- a/drivers/media/i2c/soc_camera/mt9t112.c
+++ b/drivers/media/i2c/soc_camera/mt9t112.c
@@ -904,12 +904,17 @@ static int mt9t112_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
return mt9t112_set_params(priv, rect, priv->format->code);
}
-static int mt9t112_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9t112_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t112_priv *priv = to_mt9t112(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = priv->frame.width;
mf->height = priv->frame.height;
mf->colorspace = priv->format->colorspace;
@@ -940,14 +945,19 @@ static int mt9t112_s_fmt(struct v4l2_subdev *sd,
return ret;
}
-static int mt9t112_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9t112_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t112_priv *priv = to_mt9t112(client);
unsigned int top, left;
int i;
+ if (format->pad)
+ return -EINVAL;
+
for (i = 0; i < priv->num_formats; i++)
if (mt9t112_cfmts[i].code == mf->code)
break;
@@ -963,19 +973,23 @@ static int mt9t112_try_fmt(struct v4l2_subdev *sd,
mf->field = V4L2_FIELD_NONE;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return mt9t112_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
-static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9t112_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t112_priv *priv = to_mt9t112(client);
- if (index >= priv->num_formats)
+ if (code->pad || code->index >= priv->num_formats)
return -EINVAL;
- *code = mt9t112_cfmts[index].code;
+ code->code = mt9t112_cfmts[code->index].code;
return 0;
}
@@ -1010,23 +1024,26 @@ 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,
- .g_mbus_fmt = mt9t112_g_fmt,
- .s_mbus_fmt = mt9t112_s_fmt,
- .try_mbus_fmt = mt9t112_try_fmt,
.cropcap = mt9t112_cropcap,
.g_crop = mt9t112_g_crop,
.s_crop = mt9t112_s_crop,
- .enum_mbus_fmt = mt9t112_enum_fmt,
.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_fmt = mt9t112_get_fmt,
+ .set_fmt = mt9t112_set_fmt,
+};
+
/************************************************************************
i2c driver
************************************************************************/
static struct v4l2_subdev_ops mt9t112_subdev_ops = {
.core = &mt9t112_subdev_core_ops,
.video = &mt9t112_subdev_video_ops,
+ .pad = &mt9t112_subdev_pad_ops,
};
static int mt9t112_camera_probe(struct i2c_client *client)
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index a246d4d64b8b..f31377408550 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -375,12 +375,17 @@ static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int mt9v022_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9v022_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9v022 *mt9v022 = to_mt9v022(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = mt9v022->rect.width;
mf->height = mt9v022->rect.height;
mf->code = mt9v022->fmt->code;
@@ -407,7 +412,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
/*
* The caller provides a supported format, as verified per call to
- * .try_mbus_fmt(), datawidth is from our supported format list
+ * .set_fmt(FORMAT_TRY), datawidth is from our supported format list
*/
switch (mf->code) {
case MEDIA_BUS_FMT_Y8_1X8:
@@ -437,15 +442,20 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
return ret;
}
-static int mt9v022_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9v022_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9v022 *mt9v022 = to_mt9v022(client);
const struct mt9v022_datafmt *fmt;
int align = mf->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
mf->code == MEDIA_BUS_FMT_SBGGR10_1X10;
+ if (format->pad)
+ return -EINVAL;
+
v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH,
MT9V022_MAX_WIDTH, align,
&mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top,
@@ -460,6 +470,9 @@ static int mt9v022_try_fmt(struct v4l2_subdev *sd,
mf->colorspace = fmt->colorspace;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return mt9v022_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
@@ -758,16 +771,17 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
.s_power = mt9v022_s_power,
};
-static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9v022_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9v022 *mt9v022 = to_mt9v022(client);
- if (index >= mt9v022->num_fmts)
+ if (code->pad || code->index >= mt9v022->num_fmts)
return -EINVAL;
- *code = mt9v022->fmts[index].code;
+ code->code = mt9v022->fmts[code->index].code;
return 0;
}
@@ -839,13 +853,9 @@ 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_mbus_fmt = mt9v022_s_fmt,
- .g_mbus_fmt = mt9v022_g_fmt,
- .try_mbus_fmt = mt9v022_try_fmt,
.s_crop = mt9v022_s_crop,
.g_crop = mt9v022_g_crop,
.cropcap = mt9v022_cropcap,
- .enum_mbus_fmt = mt9v022_enum_fmt,
.g_mbus_config = mt9v022_g_mbus_config,
.s_mbus_config = mt9v022_s_mbus_config,
};
@@ -854,10 +864,17 @@ static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
.g_skip_top_lines = mt9v022_g_skip_top_lines,
};
+static const struct v4l2_subdev_pad_ops mt9v022_subdev_pad_ops = {
+ .enum_mbus_code = mt9v022_enum_mbus_code,
+ .get_fmt = mt9v022_get_fmt,
+ .set_fmt = mt9v022_set_fmt,
+};
+
static struct v4l2_subdev_ops mt9v022_subdev_ops = {
.core = &mt9v022_subdev_core_ops,
.video = &mt9v022_subdev_video_ops,
.sensor = &mt9v022_subdev_sensor_ops,
+ .pad = &mt9v022_subdev_pad_ops,
};
static int mt9v022_probe(struct i2c_client *client,
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index e3c907a97765..9b4f5deec748 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -845,12 +845,17 @@ err:
return ret;
}
-static int ov2640_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov2640_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2640_priv *priv = to_ov2640(client);
+ if (format->pad)
+ return -EINVAL;
+
if (!priv->win) {
u32 width = SVGA_WIDTH, height = SVGA_HEIGHT;
priv->win = ov2640_select_win(&width, &height);
@@ -876,33 +881,16 @@ static int ov2640_g_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int ov2640_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov2640_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
- int ret;
+ if (format->pad)
+ return -EINVAL;
- switch (mf->code) {
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
- mf->colorspace = V4L2_COLORSPACE_SRGB;
- break;
- default:
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
- mf->colorspace = V4L2_COLORSPACE_JPEG;
- }
-
- ret = ov2640_set_params(client, &mf->width, &mf->height, mf->code);
-
- return ret;
-}
-
-static int ov2640_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
/*
* select suitable win, but don't store it
*/
@@ -922,16 +910,21 @@ static int ov2640_try_fmt(struct v4l2_subdev *sd,
mf->colorspace = V4L2_COLORSPACE_JPEG;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov2640_set_params(client, &mf->width,
+ &mf->height, mf->code);
+ cfg->try_fmt = *mf;
return 0;
}
-static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov2640_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov2640_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(ov2640_codes))
return -EINVAL;
- *code = ov2640_codes[index];
+ code->code = ov2640_codes[code->index];
return 0;
}
@@ -1031,18 +1024,21 @@ 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,
- .g_mbus_fmt = ov2640_g_fmt,
- .s_mbus_fmt = ov2640_s_fmt,
- .try_mbus_fmt = ov2640_try_fmt,
.cropcap = ov2640_cropcap,
.g_crop = ov2640_g_crop,
- .enum_mbus_fmt = ov2640_enum_fmt,
.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_fmt = ov2640_get_fmt,
+ .set_fmt = ov2640_set_fmt,
+};
+
static struct v4l2_subdev_ops ov2640_subdev_ops = {
.core = &ov2640_subdev_core_ops,
.video = &ov2640_subdev_video_ops,
+ .pad = &ov2640_subdev_pad_ops,
};
/* OF probe functions */
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c
index 93ae031bdafb..bab9ac0c1764 100644
--- a/drivers/media/i2c/soc_camera/ov5642.c
+++ b/drivers/media/i2c/soc_camera/ov5642.c
@@ -786,50 +786,50 @@ static int ov5642_set_resolution(struct v4l2_subdev *sd)
return ret;
}
-static int ov5642_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov5642_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov5642 *priv = to_ov5642(client);
const struct ov5642_datafmt *fmt = ov5642_find_datafmt(mf->code);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = priv->crop_rect.width;
mf->height = priv->crop_rect.height;
if (!fmt) {
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
mf->code = ov5642_colour_fmts[0].code;
mf->colorspace = ov5642_colour_fmts[0].colorspace;
}
mf->field = V4L2_FIELD_NONE;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ priv->fmt = ov5642_find_datafmt(mf->code);
+ else
+ cfg->try_fmt = *mf;
return 0;
}
-static int ov5642_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct ov5642 *priv = to_ov5642(client);
-
- /* MIPI CSI could have changed the format, double-check */
- if (!ov5642_find_datafmt(mf->code))
- return -EINVAL;
-
- ov5642_try_fmt(sd, mf);
- priv->fmt = ov5642_find_datafmt(mf->code);
-
- return 0;
-}
-
-static int ov5642_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov5642_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov5642 *priv = to_ov5642(client);
const struct ov5642_datafmt *fmt = priv->fmt;
+ if (format->pad)
+ return -EINVAL;
+
mf->code = fmt->code;
mf->colorspace = fmt->colorspace;
mf->width = priv->crop_rect.width;
@@ -839,13 +839,14 @@ static int ov5642_g_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov5642_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov5642_colour_fmts))
+ if (code->pad || code->index >= ARRAY_SIZE(ov5642_colour_fmts))
return -EINVAL;
- *code = ov5642_colour_fmts[index].code;
+ code->code = ov5642_colour_fmts[code->index].code;
return 0;
}
@@ -939,16 +940,18 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on)
}
static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
- .s_mbus_fmt = ov5642_s_fmt,
- .g_mbus_fmt = ov5642_g_fmt,
- .try_mbus_fmt = ov5642_try_fmt,
- .enum_mbus_fmt = ov5642_enum_fmt,
.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_fmt = ov5642_get_fmt,
+ .set_fmt = ov5642_set_fmt,
+};
+
static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
.s_power = ov5642_s_power,
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -960,6 +963,7 @@ static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
static struct v4l2_subdev_ops ov5642_subdev_ops = {
.core = &ov5642_subdev_core_ops,
.video = &ov5642_subdev_video_ops,
+ .pad = &ov5642_subdev_pad_ops,
};
static int ov5642_video_probe(struct i2c_client *client)
diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c
index f4eef2fa6f6f..1f8af1ee8352 100644
--- a/drivers/media/i2c/soc_camera/ov6650.c
+++ b/drivers/media/i2c/soc_camera/ov6650.c
@@ -499,12 +499,17 @@ static int ov6650_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int ov6650_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov6650_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov6650 *priv = to_ov6650(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = priv->rect.width >> priv->half_scale;
mf->height = priv->rect.height >> priv->half_scale;
mf->code = priv->code;
@@ -680,16 +685,20 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
mf->width = priv->rect.width >> half_scale;
mf->height = priv->rect.height >> half_scale;
}
-
return ret;
}
-static int ov6650_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov6650_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov6650 *priv = to_ov6650(client);
+ if (format->pad)
+ return -EINVAL;
+
if (is_unscaled_ok(mf->width, mf->height, &priv->rect))
v4l_bound_align_image(&mf->width, 2, W_CIF, 1,
&mf->height, 2, H_CIF, 1, 0);
@@ -713,16 +722,21 @@ static int ov6650_try_fmt(struct v4l2_subdev *sd,
break;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov6650_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
+
return 0;
}
-static int ov6650_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov6650_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov6650_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(ov6650_codes))
return -EINVAL;
- *code = ov6650_codes[index];
+ code->code = ov6650_codes[code->index];
return 0;
}
@@ -929,10 +943,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,
- .g_mbus_fmt = ov6650_g_fmt,
- .s_mbus_fmt = ov6650_s_fmt,
- .try_mbus_fmt = ov6650_try_fmt,
- .enum_mbus_fmt = ov6650_enum_fmt,
.cropcap = ov6650_cropcap,
.g_crop = ov6650_g_crop,
.s_crop = ov6650_s_crop,
@@ -942,9 +952,16 @@ static struct v4l2_subdev_video_ops ov6650_video_ops = {
.s_mbus_config = ov6650_s_mbus_config,
};
+static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
+ .enum_mbus_code = ov6650_enum_mbus_code,
+ .get_fmt = ov6650_get_fmt,
+ .set_fmt = ov6650_set_fmt,
+};
+
static struct v4l2_subdev_ops ov6650_subdev_ops = {
.core = &ov6650_core_ops,
.video = &ov6650_video_ops,
+ .pad = &ov6650_pad_ops,
};
/*
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c
index 8daac88b33fe..f150a8bd94dc 100644
--- a/drivers/media/i2c/soc_camera/ov772x.c
+++ b/drivers/media/i2c/soc_camera/ov772x.c
@@ -876,11 +876,16 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int ov772x_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov772x_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct ov772x_priv *priv = to_ov772x(sd);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = priv->win->rect.width;
mf->height = priv->win->rect.height;
mf->code = priv->cfmt->code;
@@ -915,12 +920,17 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
return 0;
}
-static int ov772x_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov772x_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
const struct ov772x_color_format *cfmt;
const struct ov772x_win_size *win;
+ if (format->pad)
+ return -EINVAL;
+
ov772x_select_params(mf, &cfmt, &win);
mf->code = cfmt->code;
@@ -929,6 +939,9 @@ static int ov772x_try_fmt(struct v4l2_subdev *sd,
mf->field = V4L2_FIELD_NONE;
mf->colorspace = cfmt->colorspace;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov772x_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
@@ -989,13 +1002,14 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
.s_power = ov772x_s_power,
};
-static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov772x_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov772x_cfmts))
+ if (code->pad || code->index >= ARRAY_SIZE(ov772x_cfmts))
return -EINVAL;
- *code = ov772x_cfmts[index].code;
+ code->code = ov772x_cfmts[code->index].code;
return 0;
}
@@ -1016,18 +1030,21 @@ 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,
- .g_mbus_fmt = ov772x_g_fmt,
- .s_mbus_fmt = ov772x_s_fmt,
- .try_mbus_fmt = ov772x_try_fmt,
.cropcap = ov772x_cropcap,
.g_crop = ov772x_g_crop,
- .enum_mbus_fmt = ov772x_enum_fmt,
.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_fmt = ov772x_get_fmt,
+ .set_fmt = ov772x_set_fmt,
+};
+
static struct v4l2_subdev_ops ov772x_subdev_ops = {
.core = &ov772x_subdev_core_ops,
.video = &ov772x_subdev_video_ops,
+ .pad = &ov772x_subdev_pad_ops,
};
/*
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c
index aa93d2e88572..8caae1c07541 100644
--- a/drivers/media/i2c/soc_camera/ov9640.c
+++ b/drivers/media/i2c/soc_camera/ov9640.c
@@ -519,9 +519,15 @@ static int ov9640_s_fmt(struct v4l2_subdev *sd,
return ret;
}
-static int ov9640_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov9640_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
+
ov9640_res_roundup(&mf->width, &mf->height);
mf->field = V4L2_FIELD_NONE;
@@ -537,16 +543,21 @@ static int ov9640_try_fmt(struct v4l2_subdev *sd,
mf->colorspace = V4L2_COLORSPACE_JPEG;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov9640_s_fmt(sd, mf);
+
+ cfg->try_fmt = *mf;
return 0;
}
-static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov9640_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov9640_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(ov9640_codes))
return -EINVAL;
- *code = ov9640_codes[index];
+ code->code = ov9640_codes[code->index];
return 0;
}
@@ -656,17 +667,20 @@ static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
static struct v4l2_subdev_video_ops ov9640_video_ops = {
.s_stream = ov9640_s_stream,
- .s_mbus_fmt = ov9640_s_fmt,
- .try_mbus_fmt = ov9640_try_fmt,
- .enum_mbus_fmt = ov9640_enum_fmt,
.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,
+ .set_fmt = ov9640_set_fmt,
+};
+
static struct v4l2_subdev_ops ov9640_subdev_ops = {
.core = &ov9640_core_ops,
.video = &ov9640_video_ops,
+ .pad = &ov9640_pad_ops,
};
/*
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c
index 841dc55457cf..03a7fc7316ae 100644
--- a/drivers/media/i2c/soc_camera/ov9740.c
+++ b/drivers/media/i2c/soc_camera/ov9740.c
@@ -704,25 +704,35 @@ static int ov9740_s_fmt(struct v4l2_subdev *sd,
return ret;
}
-static int ov9740_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov9740_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
+
ov9740_res_roundup(&mf->width, &mf->height);
mf->field = V4L2_FIELD_NONE;
mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
mf->colorspace = V4L2_COLORSPACE_SRGB;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov9740_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
-static int ov9740_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov9740_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov9740_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(ov9740_codes))
return -EINVAL;
- *code = ov9740_codes[index];
+ code->code = ov9740_codes[code->index];
return 0;
}
@@ -904,9 +914,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,
- .s_mbus_fmt = ov9740_s_fmt,
- .try_mbus_fmt = ov9740_try_fmt,
- .enum_mbus_fmt = ov9740_enum_fmt,
.cropcap = ov9740_cropcap,
.g_crop = ov9740_g_crop,
.g_mbus_config = ov9740_g_mbus_config,
@@ -920,9 +927,15 @@ static struct v4l2_subdev_core_ops ov9740_core_ops = {
#endif
};
+static const struct v4l2_subdev_pad_ops ov9740_pad_ops = {
+ .enum_mbus_code = ov9740_enum_mbus_code,
+ .set_fmt = ov9740_set_fmt,
+};
+
static struct v4l2_subdev_ops ov9740_subdev_ops = {
- .core = &ov9740_core_ops,
- .video = &ov9740_video_ops,
+ .core = &ov9740_core_ops,
+ .video = &ov9740_video_ops,
+ .pad = &ov9740_pad_ops,
};
static const struct v4l2_ctrl_ops ov9740_ctrl_ops = {
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
index 1752428c43c5..c769cf663f84 100644
--- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c
+++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
@@ -485,13 +485,14 @@ static int reg_write_multiple(struct i2c_client *client,
return 0;
}
-static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int rj54n1_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(rj54n1_colour_fmts))
+ if (code->pad || code->index >= ARRAY_SIZE(rj54n1_colour_fmts))
return -EINVAL;
- *code = rj54n1_colour_fmts[index].code;
+ code->code = rj54n1_colour_fmts[code->index].code;
return 0;
}
@@ -597,12 +598,17 @@ static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int rj54n1_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int rj54n1_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct rj54n1 *rj54n1 = to_rj54n1(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->code = rj54n1->fmt->code;
mf->colorspace = rj54n1->fmt->colorspace;
mf->field = V4L2_FIELD_NONE;
@@ -959,17 +965,25 @@ static int rj54n1_reg_init(struct i2c_client *client)
return ret;
}
-static int rj54n1_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int rj54n1_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct rj54n1 *rj54n1 = to_rj54n1(client);
const struct rj54n1_datafmt *fmt;
+ int output_w, output_h, max_w, max_h,
+ input_w = rj54n1->rect.width, input_h = rj54n1->rect.height;
int align = mf->code == MEDIA_BUS_FMT_SBGGR10_1X10 ||
mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE ||
mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE ||
mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE ||
mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE;
+ int ret;
+
+ if (format->pad)
+ return -EINVAL;
dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
__func__, mf->code, mf->width, mf->height);
@@ -987,24 +1001,10 @@ static int rj54n1_try_fmt(struct v4l2_subdev *sd,
v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align,
&mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0);
- return 0;
-}
-
-static int rj54n1_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct rj54n1 *rj54n1 = to_rj54n1(client);
- const struct rj54n1_datafmt *fmt;
- int output_w, output_h, max_w, max_h,
- input_w = rj54n1->rect.width, input_h = rj54n1->rect.height;
- int ret;
-
- /*
- * The host driver can call us without .try_fmt(), so, we have to take
- * care ourseleves
- */
- rj54n1_try_fmt(sd, mf);
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
/*
* Verify if the sensor has just been powered on. TODO: replace this
@@ -1020,9 +1020,6 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd,
return ret;
}
- dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
- __func__, mf->code, mf->width, mf->height);
-
/* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */
switch (mf->code) {
case MEDIA_BUS_FMT_YUYV8_2X8:
@@ -1249,10 +1246,6 @@ 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,
- .s_mbus_fmt = rj54n1_s_fmt,
- .g_mbus_fmt = rj54n1_g_fmt,
- .try_mbus_fmt = rj54n1_try_fmt,
- .enum_mbus_fmt = rj54n1_enum_fmt,
.g_crop = rj54n1_g_crop,
.s_crop = rj54n1_s_crop,
.cropcap = rj54n1_cropcap,
@@ -1260,9 +1253,16 @@ static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
.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_fmt = rj54n1_get_fmt,
+ .set_fmt = rj54n1_set_fmt,
+};
+
static struct v4l2_subdev_ops rj54n1_subdev_ops = {
.core = &rj54n1_subdev_core_ops,
.video = &rj54n1_subdev_video_ops,
+ .pad = &rj54n1_subdev_pad_ops,
};
/*
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c
index 9b853215d146..42bec9bf1892 100644
--- a/drivers/media/i2c/soc_camera/tw9910.c
+++ b/drivers/media/i2c/soc_camera/tw9910.c
@@ -691,12 +691,17 @@ static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
return 0;
}
-static int tw9910_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int tw9910_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct tw9910_priv *priv = to_tw9910(client);
+ if (format->pad)
+ return -EINVAL;
+
if (!priv->scale) {
priv->scale = tw9910_select_norm(priv->norm, 640, 480);
if (!priv->scale)
@@ -737,13 +742,18 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd,
return ret;
}
-static int tw9910_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int tw9910_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct tw9910_priv *priv = to_tw9910(client);
const struct tw9910_scale_ctrl *scale;
+ if (format->pad)
+ return -EINVAL;
+
if (V4L2_FIELD_ANY == mf->field) {
mf->field = V4L2_FIELD_INTERLACED_BT;
} else if (V4L2_FIELD_INTERLACED_BT != mf->field) {
@@ -764,6 +774,9 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd,
mf->width = scale->width;
mf->height = scale->height;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return tw9910_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
@@ -821,13 +834,14 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
.s_power = tw9910_s_power,
};
-static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int tw9910_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index)
+ if (code->pad || code->index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
return 0;
}
@@ -880,20 +894,23 @@ 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,
- .g_mbus_fmt = tw9910_g_fmt,
- .s_mbus_fmt = tw9910_s_fmt,
- .try_mbus_fmt = tw9910_try_fmt,
.cropcap = tw9910_cropcap,
.g_crop = tw9910_g_crop,
- .enum_mbus_fmt = tw9910_enum_fmt,
.g_mbus_config = tw9910_g_mbus_config,
.s_mbus_config = tw9910_s_mbus_config,
.g_tvnorms = tw9910_g_tvnorms,
};
+static const struct v4l2_subdev_pad_ops tw9910_subdev_pad_ops = {
+ .enum_mbus_code = tw9910_enum_mbus_code,
+ .get_fmt = tw9910_get_fmt,
+ .set_fmt = tw9910_set_fmt,
+};
+
static struct v4l2_subdev_ops tw9910_subdev_ops = {
.core = &tw9910_subdev_core_ops,
.video = &tw9910_subdev_video_ops,
+ .pad = &tw9910_subdev_pad_ops,
};
/*
diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c
index 10c735c3a082..b62b6ddc4356 100644
--- a/drivers/media/i2c/sr030pc30.c
+++ b/drivers/media/i2c/sr030pc30.c
@@ -471,25 +471,31 @@ static int sr030pc30_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
}
-static int sr030pc30_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int sr030pc30_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (!code || index >= ARRAY_SIZE(sr030pc30_formats))
+ if (!code || code->pad ||
+ code->index >= ARRAY_SIZE(sr030pc30_formats))
return -EINVAL;
- *code = sr030pc30_formats[index].code;
+ code->code = sr030pc30_formats[code->index].code;
return 0;
}
-static int sr030pc30_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int sr030pc30_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf;
struct sr030pc30_info *info = to_sr030pc30(sd);
int ret;
- if (!mf)
+ if (!format || format->pad)
return -EINVAL;
+ mf = &format->format;
+
if (!info->curr_win || !info->curr_fmt) {
ret = sr030pc30_set_params(sd);
if (ret)
@@ -523,25 +529,28 @@ static const struct sr030pc30_format *try_fmt(struct v4l2_subdev *sd,
}
/* Return nearest media bus frame format. */
-static int sr030pc30_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int sr030pc30_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
- if (!sd || !mf)
- return -EINVAL;
-
- try_fmt(sd, mf);
- return 0;
-}
+ struct sr030pc30_info *info = sd ? to_sr030pc30(sd) : NULL;
+ const struct sr030pc30_format *fmt;
+ struct v4l2_mbus_framefmt *mf;
-static int sr030pc30_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct sr030pc30_info *info = to_sr030pc30(sd);
+ if (!sd || !format)
+ return -EINVAL;
- if (!sd || !mf)
+ mf = &format->format;
+ if (format->pad)
return -EINVAL;
- info->curr_fmt = try_fmt(sd, mf);
+ fmt = try_fmt(sd, mf);
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
+
+ info->curr_fmt = fmt;
return sr030pc30_set_params(sd);
}
@@ -636,16 +645,15 @@ static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
.querymenu = v4l2_subdev_querymenu,
};
-static const struct v4l2_subdev_video_ops sr030pc30_video_ops = {
- .g_mbus_fmt = sr030pc30_g_fmt,
- .s_mbus_fmt = sr030pc30_s_fmt,
- .try_mbus_fmt = sr030pc30_try_fmt,
- .enum_mbus_fmt = sr030pc30_enum_fmt,
+static const struct v4l2_subdev_pad_ops sr030pc30_pad_ops = {
+ .enum_mbus_code = sr030pc30_enum_mbus_code,
+ .get_fmt = sr030pc30_get_fmt,
+ .set_fmt = sr030pc30_set_fmt,
};
static const struct v4l2_subdev_ops sr030pc30_ops = {
.core = &sr030pc30_core_ops,
- .video = &sr030pc30_video_ops,
+ .pad = &sr030pc30_pad_ops,
};
/*
diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c
index 070c152da95a..0c50e5285cf6 100644
--- a/drivers/media/i2c/tvaudio.c
+++ b/drivers/media/i2c/tvaudio.c
@@ -272,7 +272,7 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
return -EINVAL;
}
- /* FIXME: it seems that the shadow bytes are wrong bellow !*/
+ /* FIXME: it seems that the shadow bytes are wrong below !*/
/* update our shadow register set; print bytes if (debug > 0) */
v4l2_dbg(1, debug, sd, "chip_cmd(%s): reg=%d, data:",
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index 1c6bc306ecdc..24e47279e30c 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -747,54 +747,6 @@ static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl)
}
/**
- * tvp514x_enum_mbus_fmt() - V4L2 decoder interface handler for enum_mbus_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @index: index of pixelcode to retrieve
- * @code: receives the pixelcode
- *
- * Enumerates supported mediabus formats
- */
-static int
-tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
-{
- if (index)
- return -EINVAL;
-
- *code = MEDIA_BUS_FMT_YUYV10_2X10;
- return 0;
-}
-
-/**
- * tvp514x_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to the mediabus format structure
- *
- * Negotiates the image capture size and mediabus format.
- */
-static int
-tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- struct tvp514x_decoder *decoder = to_decoder(sd);
- enum tvp514x_std current_std;
-
- if (f == NULL)
- return -EINVAL;
-
- /* Calculate height and width based on current standard */
- current_std = decoder->current_std;
-
- f->code = MEDIA_BUS_FMT_YUYV8_2X8;
- f->width = decoder->std_list[current_std].width;
- f->height = decoder->std_list[current_std].height;
- f->field = V4L2_FIELD_INTERLACED;
- f->colorspace = V4L2_COLORSPACE_SMPTE170M;
- v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n",
- f->width, f->height);
- return 0;
-}
-
-/**
* tvp514x_g_parm() - V4L2 decoder interface handler for g_parm
* @sd: pointer to standard V4L2 sub-device structure
* @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
@@ -962,6 +914,9 @@ static int tvp514x_get_pad_format(struct v4l2_subdev *sd,
struct tvp514x_decoder *decoder = to_decoder(sd);
__u32 which = format->which;
+ if (format->pad)
+ return -EINVAL;
+
if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
format->format = decoder->format;
return 0;
@@ -1016,10 +971,6 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = {
.s_std = tvp514x_s_std,
.s_routing = tvp514x_s_routing,
.querystd = tvp514x_querystd,
- .enum_mbus_fmt = tvp514x_enum_mbus_fmt,
- .g_mbus_fmt = tvp514x_mbus_fmt,
- .try_mbus_fmt = tvp514x_mbus_fmt,
- .s_mbus_fmt = tvp514x_mbus_fmt,
.g_parm = tvp514x_g_parm,
.s_parm = tvp514x_s_parm,
.s_stream = tvp514x_s_stream,
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 68cdab9c0903..e4fa0746f75e 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -817,24 +817,29 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
}
}
-static int tvp5150_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index)
+ if (code->pad || code->index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
return 0;
}
-static int tvp5150_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *f)
+static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *f;
struct tvp5150 *decoder = to_tvp5150(sd);
- if (f == NULL)
+ if (!format || format->pad)
return -EINVAL;
+ f = &format->format;
+
tvp5150_reset(sd, 0);
f->width = decoder->rect.width;
@@ -1068,10 +1073,6 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
.s_std = tvp5150_s_std,
.s_routing = tvp5150_s_routing,
- .enum_mbus_fmt = tvp5150_enum_mbus_fmt,
- .s_mbus_fmt = tvp5150_mbus_fmt,
- .try_mbus_fmt = tvp5150_mbus_fmt,
- .g_mbus_fmt = tvp5150_mbus_fmt,
.s_crop = tvp5150_s_crop,
.g_crop = tvp5150_g_crop,
.cropcap = tvp5150_cropcap,
@@ -1084,11 +1085,18 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
.s_raw_fmt = tvp5150_s_raw_fmt,
};
+static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
+ .enum_mbus_code = tvp5150_enum_mbus_code,
+ .set_fmt = tvp5150_fill_fmt,
+ .get_fmt = tvp5150_fill_fmt,
+};
+
static const struct v4l2_subdev_ops tvp5150_ops = {
.core = &tvp5150_core_ops,
.tuner = &tvp5150_tuner_ops,
.video = &tvp5150_video_ops,
.vbi = &tvp5150_vbi_ops,
+ .pad = &tvp5150_pad_ops,
};
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index 787cdfb08749..05077cffd235 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -611,31 +611,6 @@ static int tvp7002_s_ctrl(struct v4l2_ctrl *ctrl)
}
/*
- * tvp7002_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to mediabus format structure
- *
- * Negotiate the image capture size and mediabus format.
- * There is only one possible format, so this single function works for
- * get, set and try.
- */
-static int tvp7002_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- struct tvp7002 *device = to_tvp7002(sd);
- const struct v4l2_bt_timings *bt = &device->current_timings->timings.bt;
-
- f->width = bt->width;
- f->height = bt->height;
- f->code = MEDIA_BUS_FMT_YUYV10_1X20;
- f->field = device->current_timings->scanmode;
- f->colorspace = device->current_timings->color_space;
-
- v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d",
- f->width, f->height);
- return 0;
-}
-
-/*
* tvp7002_query_dv() - query DV timings
* @sd: pointer to standard V4L2 sub-device structure
* @index: index into the tvp7002_timings array
@@ -747,25 +722,6 @@ static int tvp7002_s_register(struct v4l2_subdev *sd,
#endif
/*
- * tvp7002_enum_mbus_fmt() - Enum supported mediabus formats
- * @sd: pointer to standard V4L2 sub-device structure
- * @index: format index
- * @code: pointer to mediabus format
- *
- * Enumerate supported mediabus formats.
- */
-
-static int tvp7002_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
-{
- /* Check requested format index is within range */
- if (index)
- return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV10_1X20;
- return 0;
-}
-
-/*
* tvp7002_s_stream() - V4L2 decoder i/f handler for s_stream
* @sd: pointer to standard V4L2 sub-device structure
* @enable: streaming enable or disable
@@ -924,10 +880,6 @@ static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
.s_dv_timings = tvp7002_s_dv_timings,
.query_dv_timings = tvp7002_query_dv_timings,
.s_stream = tvp7002_s_stream,
- .g_mbus_fmt = tvp7002_mbus_fmt,
- .try_mbus_fmt = tvp7002_mbus_fmt,
- .s_mbus_fmt = tvp7002_mbus_fmt,
- .enum_mbus_fmt = tvp7002_enum_mbus_fmt,
};
/* media pad related operation handlers */
diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c
index 00e7f043977e..4c72a18c0b8c 100644
--- a/drivers/media/i2c/vs6624.c
+++ b/drivers/media/i2c/vs6624.c
@@ -557,21 +557,28 @@ static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
}
-static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int vs6624_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(vs6624_formats))
+ if (code->pad || code->index >= ARRAY_SIZE(vs6624_formats))
return -EINVAL;
- *code = vs6624_formats[index].mbus_code;
+ code->code = vs6624_formats[code->index].mbus_code;
return 0;
}
-static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int vs6624_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+ struct vs6624 *sensor = to_vs6624(sd);
int index;
+ if (format->pad)
+ return -EINVAL;
+
for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++)
if (vs6624_formats[index].mbus_code == fmt->code)
break;
@@ -590,18 +597,11 @@ static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd,
fmt->height = fmt->height & (~3);
fmt->field = V4L2_FIELD_NONE;
fmt->colorspace = vs6624_formats[index].colorspace;
- return 0;
-}
-
-static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
-{
- struct vs6624 *sensor = to_vs6624(sd);
- int ret;
- ret = vs6624_try_mbus_fmt(sd, fmt);
- if (ret)
- return ret;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *fmt;
+ return 0;
+ }
/* set image format */
switch (fmt->code) {
@@ -648,12 +648,16 @@ static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int vs6624_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int vs6624_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct vs6624 *sensor = to_vs6624(sd);
- *fmt = sensor->fmt;
+ if (format->pad)
+ return -EINVAL;
+
+ format->format = sensor->fmt;
return 0;
}
@@ -738,18 +742,21 @@ static const struct v4l2_subdev_core_ops vs6624_core_ops = {
};
static const struct v4l2_subdev_video_ops vs6624_video_ops = {
- .enum_mbus_fmt = vs6624_enum_mbus_fmt,
- .try_mbus_fmt = vs6624_try_mbus_fmt,
- .s_mbus_fmt = vs6624_s_mbus_fmt,
- .g_mbus_fmt = vs6624_g_mbus_fmt,
.s_parm = vs6624_s_parm,
.g_parm = vs6624_g_parm,
.s_stream = vs6624_s_stream,
};
+static const struct v4l2_subdev_pad_ops vs6624_pad_ops = {
+ .enum_mbus_code = vs6624_enum_mbus_code,
+ .get_fmt = vs6624_get_fmt,
+ .set_fmt = vs6624_set_fmt,
+};
+
static const struct v4l2_subdev_ops vs6624_ops = {
.core = &vs6624_core_ops,
.video = &vs6624_video_ops,
+ .pad = &vs6624_pad_ops,
};
static int vs6624_probe(struct i2c_client *client,