From: Vaibhav Hiremath <hvaibhav@xxxxxx> Migrate tvp5146 driver to media controller framework. The driver registers as a sub-device entity to MC framwork and sub-device to V4L2 layer. The default format code was V4L2_MBUS_FMT_YUYV10_2X10. Changed it to V4L2_MBUS_FMT_UYVY8_2X8 and hence added the new format code to ccdc and isp format arrays. Signed-off-by: Vaibhav Hiremath <hvaibhav@xxxxxx> Signed-off-by: Deepthy Ravi <deepthy.ravi@xxxxxx> --- drivers/media/video/omap3isp/ispccdc.c | 1 + drivers/media/video/omap3isp/ispvideo.c | 3 + drivers/media/video/tvp514x.c | 241 ++++++++++++++++++++++++++++--- include/media/v4l2-subdev.h | 7 +- 4 files changed, 222 insertions(+), 30 deletions(-) diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index 9d3459d..d58fe45 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c @@ -57,6 +57,7 @@ static const unsigned int ccdc_fmts[] = { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SGBRG12_1X12, + V4L2_MBUS_FMT_UYVY8_2X8, }; /* diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c index fd965ad..d5b8236 100644 --- a/drivers/media/video/omap3isp/ispvideo.c +++ b/drivers/media/video/omap3isp/ispvideo.c @@ -100,6 +100,9 @@ static struct isp_format_info formats[] = { { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, 0, V4L2_PIX_FMT_YUYV, 16, }, + { V4L2_MBUS_FMT_UYVY8_2X8, V4L2_MBUS_FMT_UYVY8_2X8, + V4L2_MBUS_FMT_UYVY8_2X8, 0, + V4L2_PIX_FMT_UYVY, 16, }, }; const struct isp_format_info * diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index 9b3e828..10f3e87 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -32,11 +32,14 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/videodev2.h> +#include <linux/v4l2-mediabus.h> #include <media/v4l2-device.h> #include <media/v4l2-common.h> -#include <media/v4l2-mediabus.h> #include <media/v4l2-chip-ident.h> +#include <media/v4l2-subdev.h> +#include <media/v4l2-ctrls.h> + #include <media/v4l2-ctrls.h> #include <media/tvp514x.h> @@ -78,6 +81,8 @@ struct tvp514x_std_info { unsigned long height; u8 video_std; struct v4l2_standard standard; + unsigned int mbus_code; + struct v4l2_mbus_framefmt format; }; static struct tvp514x_reg tvp514x_reg_list_default[0x40]; @@ -101,6 +106,7 @@ struct tvp514x_decoder { struct v4l2_ctrl_handler hdl; struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)]; const struct tvp514x_platform_data *pdata; + struct media_pad pad; int ver; int streaming; @@ -207,29 +213,46 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = { static const struct tvp514x_std_info tvp514x_std_list[] = { /* Standard: STD_NTSC_MJ */ [STD_NTSC_MJ] = { - .width = NTSC_NUM_ACTIVE_PIXELS, - .height = NTSC_NUM_ACTIVE_LINES, - .video_std = VIDEO_STD_NTSC_MJ_BIT, - .standard = { - .index = 0, - .id = V4L2_STD_NTSC, - .name = "NTSC", - .frameperiod = {1001, 30000}, - .framelines = 525 - }, - /* Standard: STD_PAL_BDGHIN */ + .width = NTSC_NUM_ACTIVE_PIXELS, + .height = NTSC_NUM_ACTIVE_LINES, + .video_std = VIDEO_STD_NTSC_MJ_BIT, + .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, + .standard = { + .index = 0, + .id = V4L2_STD_NTSC, + .name = "NTSC", + .frameperiod = {1001, 30000}, + .framelines = 525 + }, + .format = { + .width = NTSC_NUM_ACTIVE_PIXELS, + .height = NTSC_NUM_ACTIVE_LINES, + .code = V4L2_MBUS_FMT_UYVY8_2X8, + .field = V4L2_FIELD_INTERLACED, + .colorspace = V4L2_COLORSPACE_SMPTE170M, + } + }, + /* Standard: STD_PAL_BDGHIN */ [STD_PAL_BDGHIN] = { - .width = PAL_NUM_ACTIVE_PIXELS, - .height = PAL_NUM_ACTIVE_LINES, - .video_std = VIDEO_STD_PAL_BDGHIN_BIT, - .standard = { - .index = 1, - .id = V4L2_STD_PAL, - .name = "PAL", - .frameperiod = {1, 25}, - .framelines = 625 - }, + .width = PAL_NUM_ACTIVE_PIXELS, + .height = PAL_NUM_ACTIVE_LINES, + .video_std = VIDEO_STD_PAL_BDGHIN_BIT, + .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, + .standard = { + .index = 1, + .id = V4L2_STD_PAL, + .name = "PAL", + .frameperiod = {1, 25}, + .framelines = 625 + }, + .format = { + .width = PAL_NUM_ACTIVE_PIXELS, + .height = PAL_NUM_ACTIVE_LINES, + .code = V4L2_MBUS_FMT_UYVY8_2X8, + .field = V4L2_FIELD_INTERLACED, + .colorspace = V4L2_COLORSPACE_SMPTE170M, + }, }, /* Standard: need to add for additional standard */ }; @@ -792,7 +815,7 @@ tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, if (index) return -EINVAL; - *code = V4L2_MBUS_FMT_YUYV10_2X10; + *code = V4L2_MBUS_FMT_UYVY8_2X8; return 0; } @@ -815,7 +838,7 @@ tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) /* Calculate height and width based on current standard */ current_std = decoder->current_std; - f->code = V4L2_MBUS_FMT_YUYV10_2X10; + f->code = V4L2_MBUS_FMT_UYVY8_2X8; f->width = decoder->std_list[current_std].width; f->height = decoder->std_list[current_std].height; f->field = V4L2_FIELD_INTERLACED; @@ -952,11 +975,154 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) return err; } +static int tvp514x_s_power(struct v4l2_subdev *sd, int on) +{ + struct tvp514x_decoder *decoder = to_decoder(sd); + + if (decoder->pdata && decoder->pdata->s_power) + return decoder->pdata->s_power(sd, on); + + return 0; +} + +/* +* tvp514x_enum_mbus_code - V4L2 sensor interface handler for pad_ops +* @subdev: pointer to standard V4L2 sub-device structure +* @fh: pointer to standard V4L2 sub-device file handle +* @code: pointer to v4l2_subdev_pad_mbus_code_enum structure +*/ +static int tvp514x_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index >= ARRAY_SIZE(tvp514x_std_list)) + return -EINVAL; + code->code = V4L2_MBUS_FMT_UYVY8_2X8; + + return 0; +} + +static int tvp514x_get_pad_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct tvp514x_decoder *decoder = to_decoder(subdev); + enum tvp514x_std current_std; + + /* query the current standard */ + current_std = tvp514x_query_current_std(subdev); + if (current_std == STD_INVALID) { + v4l2_err(subdev, "Unable to query std\n"); + return -EINVAL; + } + + fmt->format = decoder->std_list[current_std].format; + + return 0; +} + +static int tvp514x_set_pad_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct tvp514x_decoder *decoder = to_decoder(subdev); + enum tvp514x_std current_std; + + /* query the current standard */ + current_std = tvp514x_query_current_std(subdev); + if (current_std == STD_INVALID) { + v4l2_err(subdev, "Unable to query std\n"); + return -EINVAL; + } + + fmt->format.width = decoder->std_list[current_std].width; + fmt->format.height = decoder->std_list[current_std].height; + fmt->format.code = V4L2_MBUS_FMT_UYVY8_2X8; + fmt->format.field = V4L2_FIELD_INTERLACED; + fmt->format.colorspace = V4L2_COLORSPACE_SMPTE170M; + + return 0; +} + +static int tvp514x_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct tvp514x_decoder *decoder = to_decoder(subdev); + enum tvp514x_std current_std; + + if (fse->code != V4L2_MBUS_FMT_UYVY8_2X8) + return -EINVAL; + + /* query the current standard */ + current_std = tvp514x_query_current_std(subdev); + if (current_std == STD_INVALID) { + v4l2_err(subdev, "Unable to query std\n"); + return -EINVAL; + } + + fse->min_width = decoder->std_list[current_std].width; + fse->min_height = decoder->std_list[current_std].height; + fse->max_width = fse->min_width; + fse->max_height = fse->min_height; + + return 0; +} + +/* +* V4L2 subdev internal operations +*/ +static int tvp514x_registered(struct v4l2_subdev *subdev) +{ + enum tvp514x_std current_std; + + tvp514x_s_stream(subdev, 1); + /* query the current standard */ + current_std = tvp514x_query_current_std(subdev); + if (current_std == STD_INVALID) { + v4l2_err(subdev, "Unable to query std\n"); + return -EINVAL; + } + + tvp514x_s_stream(subdev, 0); + + return 0; +} + +static int tvp514x_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) +{ + enum tvp514x_std current_std; + + tvp514x_s_stream(subdev, 1); + /* query the current standard */ + current_std = tvp514x_query_current_std(subdev); + if (current_std == STD_INVALID) { + v4l2_err(subdev, "Unable to query std\n"); + return -EINVAL; + } + + tvp514x_s_stream(subdev, 0); + + return 0; +} + +/* +* V4L2 subdev core operations +*/ +static int tvp514x_g_chip_ident(struct v4l2_subdev *subdev, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(subdev); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP5146, 0); +} + static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = { .s_ctrl = tvp514x_s_ctrl, }; static const struct v4l2_subdev_core_ops tvp514x_core_ops = { + .g_chip_ident = tvp514x_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -965,6 +1131,12 @@ static const struct v4l2_subdev_core_ops tvp514x_core_ops = { .queryctrl = v4l2_subdev_queryctrl, .querymenu = v4l2_subdev_querymenu, .s_std = tvp514x_s_std, + .s_power = tvp514x_s_power, +}; + +static struct v4l2_subdev_internal_ops tvp514x_subdev_internal_ops = { + .registered = tvp514x_registered, + .open = tvp514x_open, }; static const struct v4l2_subdev_video_ops tvp514x_video_ops = { @@ -979,9 +1151,17 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = { .s_stream = tvp514x_s_stream, }; +static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = { + .enum_mbus_code = tvp514x_enum_mbus_code, + .enum_frame_size = tvp514x_enum_frame_size, + .get_fmt = tvp514x_get_pad_format, + .set_fmt = tvp514x_set_pad_format, +}; + static const struct v4l2_subdev_ops tvp514x_ops = { .core = &tvp514x_core_ops, .video = &tvp514x_video_ops, + .pad = &tvp514x_pad_ops, }; static struct tvp514x_decoder tvp514x_dev = { @@ -1005,6 +1185,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tvp514x_decoder *decoder; struct v4l2_subdev *sd; + int ret; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -1046,6 +1227,17 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) sd = &decoder->sd; v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); + decoder->sd.internal_ops = &tvp514x_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + decoder->pad.flags = MEDIA_PAD_FL_SOURCE; + decoder->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; + ret = media_entity_init(&decoder->sd.entity, 1, &decoder->pad, 0); + if (ret < 0) { + v4l2_err(client, "failed to register as a media entity!!\n"); + kfree(decoder); + return ret; + } + v4l2_ctrl_handler_init(&decoder->hdl, 5); v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); @@ -1087,6 +1279,7 @@ static int tvp514x_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); + media_entity_cleanup(&decoder->sd.entity); kfree(decoder); return 0; } diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 257da1a..0e9aa30 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -514,9 +514,8 @@ struct v4l2_subdev_internal_ops { stand-alone or embedded in a larger struct. */ struct v4l2_subdev { -#if defined(CONFIG_MEDIA_CONTROLLER) struct media_entity entity; -#endif + struct list_head list; struct module *owner; u32 flags; @@ -547,16 +546,13 @@ struct v4l2_subdev { */ struct v4l2_subdev_fh { struct v4l2_fh vfh; -#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) struct v4l2_mbus_framefmt *try_fmt; struct v4l2_rect *try_crop; -#endif }; #define to_v4l2_subdev_fh(fh) \ container_of(fh, struct v4l2_subdev_fh, vfh) -#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) static inline struct v4l2_mbus_framefmt * v4l2_subdev_get_try_format(struct v4l2_subdev_fh *fh, unsigned int pad) { @@ -568,7 +564,6 @@ v4l2_subdev_get_try_crop(struct v4l2_subdev_fh *fh, unsigned int pad) { return &fh->try_crop[pad]; } -#endif extern const struct v4l2_file_operations v4l2_subdev_fops; -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html