#include <media/v4l2-subdev.h>
#include <media/v4l2-ctrls.h>
+/*
+ * ATTENTION: this driver still cannot be used outside of the soc-camera
+ * framework because of its PM implementation, using the video_device node.
+ * If hardware becomes available for testing, alternative PM approaches shall
+ * be considered and tested.
+ */
+
/*
* mt9t031 i2c address 0x5d
* The platform has to define i2c_board_info and link to it from
.pm = &mt9t031_dev_pm_ops,
};
+static int mt9t031_s_power(struct v4l2_subdev *sd, int on)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct video_device *vdev = soc_camera_i2c_to_vdev(client);
+
+ if (on)
+ vdev->dev.type = &mt9t031_dev_type;
+ else
+ vdev->dev.type = NULL;
+
+ return 0;
+}
+
/*
* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one
static int mt9t031_video_probe(struct i2c_client *client)
{
struct mt9t031 *mt9t031 = to_mt9t031(client);
- struct video_device *vdev = soc_camera_i2c_to_vdev(client);
s32 data;
int ret;
dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data);
ret = mt9t031_idle(client);
- if (ret < 0) {
+ if (ret < 0)
dev_err(&client->dev, "Failed to initialise the camera\n");
- } else {
- vdev->dev.type = &mt9t031_dev_type;
+ else
v4l2_ctrl_handler_setup(&mt9t031->hdl);
- }
+
return ret;
}
static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
.g_chip_ident = mt9t031_g_chip_ident,
+ .s_power = mt9t031_s_power,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9t031_g_register,
.s_register = mt9t031_s_register,
return v4l2_subdev_call(sd, core, s_std, *a);
}
+static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a)
+{
+ struct soc_camera_device *icd = file->private_data;
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+
+ return v4l2_subdev_call(sd, core, g_std, a);
+}
+
static int soc_camera_enum_fsizes(struct file *file, void *fh,
struct v4l2_frmsizeenum *fsize)
{
goto ei2cga;
}
- icl->board_info->platform_data = icd;
+ icl->board_info->platform_data = icl;
subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap,
icl->board_info, NULL);
.vidioc_g_input = soc_camera_g_input,
.vidioc_s_input = soc_camera_s_input,
.vidioc_s_std = soc_camera_s_std,
+ .vidioc_g_std = soc_camera_g_std,
.vidioc_enum_framesizes = soc_camera_enum_fsizes,
.vidioc_reqbufs = soc_camera_reqbufs,
.vidioc_querybuf = soc_camera_querybuf,
struct v4l2_subdev subdev;
struct tw9910_video_info *info;
const struct tw9910_scale_ctrl *scale;
+ v4l2_std_id norm;
u32 revision;
};
return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2);
}
-static const struct tw9910_scale_ctrl *tw9910_select_norm(struct soc_camera_device *icd,
+static const struct tw9910_scale_ctrl *tw9910_select_norm(v4l2_std_id norm,
u32 width, u32 height)
{
const struct tw9910_scale_ctrl *scale;
const struct tw9910_scale_ctrl *ret = NULL;
- v4l2_std_id norm = icd->vdev->current_norm;
__u32 diff = 0xffffffff, tmp;
int size, i;
return tw9910_power(client, enable);
}
+static int tw9910_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct tw9910_priv *priv = to_tw9910(client);
+
+ *norm = priv->norm;
+
+ return 0;
+}
+
static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
{
- int ret = -EINVAL;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct tw9910_priv *priv = to_tw9910(client);
- if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL))
- ret = 0;
+ if (!(norm & (V4L2_STD_NTSC | V4L2_STD_PAL)))
+ return -EINVAL;
- return ret;
+ priv->norm = norm;
+
+ return 0;
}
static int tw9910_g_chip_ident(struct v4l2_subdev *sd,
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct tw9910_priv *priv = to_tw9910(client);
- struct soc_camera_device *icd = client->dev.platform_data;
int ret = -EINVAL;
u8 val;
/*
* select suitable norm
*/
- priv->scale = tw9910_select_norm(icd, *width, *height);
+ priv->scale = tw9910_select_norm(priv->norm, *width, *height);
if (!priv->scale)
goto tw9910_set_fmt_error;
static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct soc_camera_device *icd = client->dev.platform_data;
+ struct tw9910_priv *priv = to_tw9910(client);
a->c.left = 0;
a->c.top = 0;
- if (icd->vdev->current_norm & V4L2_STD_NTSC) {
+ if (priv->norm & V4L2_STD_NTSC) {
a->c.width = 640;
a->c.height = 480;
} else {
static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct soc_camera_device *icd = client->dev.platform_data;
+ struct tw9910_priv *priv = to_tw9910(client);
a->bounds.left = 0;
a->bounds.top = 0;
- if (icd->vdev->current_norm & V4L2_STD_NTSC) {
+ if (priv->norm & V4L2_STD_NTSC) {
a->bounds.width = 640;
a->bounds.height = 480;
} else {
struct v4l2_mbus_framefmt *mf)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct soc_camera_device *icd = client->dev.platform_data;
+ struct tw9910_priv *priv = to_tw9910(client);
const struct tw9910_scale_ctrl *scale;
if (V4L2_FIELD_ANY == mf->field) {
/*
* select suitable norm
*/
- scale = tw9910_select_norm(icd, mf->width, mf->height);
+ scale = tw9910_select_norm(priv->norm, mf->width, mf->height);
if (!scale)
return -EINVAL;
return 0;
}
-static int tw9910_video_probe(struct soc_camera_device *icd,
- struct i2c_client *client)
+static int tw9910_video_probe(struct i2c_client *client)
{
struct tw9910_priv *priv = to_tw9910(client);
s32 id;
dev_info(&client->dev,
"tw9910 Product ID %0x:%0x\n", id, priv->revision);
- icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL;
- icd->vdev->current_norm = V4L2_STD_NTSC;
+ priv->norm = V4L2_STD_NTSC;
return 0;
}
static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
.g_chip_ident = tw9910_g_chip_ident,
.s_std = tw9910_s_std,
+ .g_std = tw9910_g_std,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = tw9910_g_register,
.s_register = tw9910_s_register,
{
struct tw9910_priv *priv;
struct tw9910_video_info *info;
- struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter =
to_i2c_adapter(client->dev.parent);
struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
- ret = tw9910_video_probe(icd, client);
+ ret = tw9910_video_probe(client);
if (ret)
kfree(priv);