diff options
author | Manjunath Hadli <manjunath.hadli@ti.com> | 2013-03-08 02:13:35 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-21 13:06:29 -0400 |
commit | 5b38b0f88d28bd1b492fe225b6d401b2e51fd8cc (patch) | |
tree | ce88ef5cd4722ec09ea96268cdbdf5f029972c0c | |
parent | e64171b97b88a1adf297d429826fdbb9e232ab53 (diff) |
[media] media: tvp514x: enable TVP514X for media controller based usage
add support for TVP514x as a media entity and support for
pad operations. The decoder supports 1 output pad.
The default format code was V4L2_MBUS_FMT_YUYV10_2X10
changed it to V4L2_MBUS_FMT_UYVY8_2X8.
Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Lad, Prabhakar <prabhakar.lad@ti.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/i2c/tvp514x.c | 163 |
1 files changed, 154 insertions, 9 deletions
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index aa94ebc2d755..ab8f3fee7e94 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * Hardik Shah <hardik.shah@ti.com> | 12 | * Hardik Shah <hardik.shah@ti.com> |
13 | * Manjunath Hadli <mrh@ti.com> | 13 | * Manjunath Hadli <mrh@ti.com> |
14 | * Karicheri Muralidharan <m-karicheri2@ti.com> | 14 | * Karicheri Muralidharan <m-karicheri2@ti.com> |
15 | * Prabhakar Lad <prabhakar.lad@ti.com> | ||
15 | * | 16 | * |
16 | * This package is free software; you can redistribute it and/or modify | 17 | * This package is free software; you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License version 2 as | 18 | * it under the terms of the GNU General Public License version 2 as |
@@ -33,6 +34,7 @@ | |||
33 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
34 | #include <linux/videodev2.h> | 35 | #include <linux/videodev2.h> |
35 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/v4l2-mediabus.h> | ||
36 | 38 | ||
37 | #include <media/v4l2-device.h> | 39 | #include <media/v4l2-device.h> |
38 | #include <media/v4l2-common.h> | 40 | #include <media/v4l2-common.h> |
@@ -40,12 +42,10 @@ | |||
40 | #include <media/v4l2-chip-ident.h> | 42 | #include <media/v4l2-chip-ident.h> |
41 | #include <media/v4l2-ctrls.h> | 43 | #include <media/v4l2-ctrls.h> |
42 | #include <media/tvp514x.h> | 44 | #include <media/tvp514x.h> |
45 | #include <media/media-entity.h> | ||
43 | 46 | ||
44 | #include "tvp514x_regs.h" | 47 | #include "tvp514x_regs.h" |
45 | 48 | ||
46 | /* Module Name */ | ||
47 | #define TVP514X_MODULE_NAME "tvp514x" | ||
48 | |||
49 | /* Private macros for TVP */ | 49 | /* Private macros for TVP */ |
50 | #define I2C_RETRY_COUNT (5) | 50 | #define I2C_RETRY_COUNT (5) |
51 | #define LOCK_RETRY_COUNT (5) | 51 | #define LOCK_RETRY_COUNT (5) |
@@ -91,6 +91,9 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); | |||
91 | * @pdata: Board specific | 91 | * @pdata: Board specific |
92 | * @ver: Chip version | 92 | * @ver: Chip version |
93 | * @streaming: TVP5146/47 decoder streaming - enabled or disabled. | 93 | * @streaming: TVP5146/47 decoder streaming - enabled or disabled. |
94 | * @pix: Current pixel format | ||
95 | * @num_fmts: Number of formats | ||
96 | * @fmt_list: Format list | ||
94 | * @current_std: Current standard | 97 | * @current_std: Current standard |
95 | * @num_stds: Number of standards | 98 | * @num_stds: Number of standards |
96 | * @std_list: Standards list | 99 | * @std_list: Standards list |
@@ -106,12 +109,20 @@ struct tvp514x_decoder { | |||
106 | int ver; | 109 | int ver; |
107 | int streaming; | 110 | int streaming; |
108 | 111 | ||
112 | struct v4l2_pix_format pix; | ||
113 | int num_fmts; | ||
114 | const struct v4l2_fmtdesc *fmt_list; | ||
115 | |||
109 | enum tvp514x_std current_std; | 116 | enum tvp514x_std current_std; |
110 | int num_stds; | 117 | int num_stds; |
111 | const struct tvp514x_std_info *std_list; | 118 | const struct tvp514x_std_info *std_list; |
112 | /* Input and Output Routing parameters */ | 119 | /* Input and Output Routing parameters */ |
113 | u32 input; | 120 | u32 input; |
114 | u32 output; | 121 | u32 output; |
122 | |||
123 | /* mc related members */ | ||
124 | struct media_pad pad; | ||
125 | struct v4l2_mbus_framefmt format; | ||
115 | }; | 126 | }; |
116 | 127 | ||
117 | /* TVP514x default register values */ | 128 | /* TVP514x default register values */ |
@@ -200,6 +211,21 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = { | |||
200 | }; | 211 | }; |
201 | 212 | ||
202 | /** | 213 | /** |
214 | * List of image formats supported by TVP5146/47 decoder | ||
215 | * Currently we are using 8 bit mode only, but can be | ||
216 | * extended to 10/20 bit mode. | ||
217 | */ | ||
218 | static const struct v4l2_fmtdesc tvp514x_fmt_list[] = { | ||
219 | { | ||
220 | .index = 0, | ||
221 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
222 | .flags = 0, | ||
223 | .description = "8-bit UYVY 4:2:2 Format", | ||
224 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
225 | }, | ||
226 | }; | ||
227 | |||
228 | /** | ||
203 | * Supported standards - | 229 | * Supported standards - |
204 | * | 230 | * |
205 | * Currently supports two standards only, need to add support for rest of the | 231 | * Currently supports two standards only, need to add support for rest of the |
@@ -733,7 +759,7 @@ tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, | |||
733 | } | 759 | } |
734 | 760 | ||
735 | /** | 761 | /** |
736 | * tvp514x_mbus_fmt_cap() - V4L2 decoder interface handler for try/s/g_mbus_fmt | 762 | * tvp514x_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt |
737 | * @sd: pointer to standard V4L2 sub-device structure | 763 | * @sd: pointer to standard V4L2 sub-device structure |
738 | * @f: pointer to the mediabus format structure | 764 | * @f: pointer to the mediabus format structure |
739 | * | 765 | * |
@@ -751,12 +777,11 @@ tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) | |||
751 | /* Calculate height and width based on current standard */ | 777 | /* Calculate height and width based on current standard */ |
752 | current_std = decoder->current_std; | 778 | current_std = decoder->current_std; |
753 | 779 | ||
754 | f->code = V4L2_MBUS_FMT_YUYV10_2X10; | 780 | f->code = V4L2_MBUS_FMT_YUYV8_2X8; |
755 | f->width = decoder->std_list[current_std].width; | 781 | f->width = decoder->std_list[current_std].width; |
756 | f->height = decoder->std_list[current_std].height; | 782 | f->height = decoder->std_list[current_std].height; |
757 | f->field = V4L2_FIELD_INTERLACED; | 783 | f->field = V4L2_FIELD_INTERLACED; |
758 | f->colorspace = V4L2_COLORSPACE_SMPTE170M; | 784 | f->colorspace = V4L2_COLORSPACE_SMPTE170M; |
759 | |||
760 | v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n", | 785 | v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n", |
761 | f->width, f->height); | 786 | f->width, f->height); |
762 | return 0; | 787 | return 0; |
@@ -892,6 +917,88 @@ static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = { | |||
892 | .s_ctrl = tvp514x_s_ctrl, | 917 | .s_ctrl = tvp514x_s_ctrl, |
893 | }; | 918 | }; |
894 | 919 | ||
920 | /** | ||
921 | * tvp514x_enum_mbus_code() - V4L2 decoder interface handler for enum_mbus_code | ||
922 | * @sd: pointer to standard V4L2 sub-device structure | ||
923 | * @fh: file handle | ||
924 | * @code: pointer to v4l2_subdev_mbus_code_enum structure | ||
925 | * | ||
926 | * Enumertaes mbus codes supported | ||
927 | */ | ||
928 | static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd, | ||
929 | struct v4l2_subdev_fh *fh, | ||
930 | struct v4l2_subdev_mbus_code_enum *code) | ||
931 | { | ||
932 | u32 pad = code->pad; | ||
933 | u32 index = code->index; | ||
934 | |||
935 | memset(code, 0, sizeof(*code)); | ||
936 | code->index = index; | ||
937 | code->pad = pad; | ||
938 | |||
939 | if (index != 0) | ||
940 | return -EINVAL; | ||
941 | |||
942 | code->code = V4L2_MBUS_FMT_YUYV8_2X8; | ||
943 | |||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | /** | ||
948 | * tvp514x_get_pad_format() - V4L2 decoder interface handler for get pad format | ||
949 | * @sd: pointer to standard V4L2 sub-device structure | ||
950 | * @fh: file handle | ||
951 | * @format: pointer to v4l2_subdev_format structure | ||
952 | * | ||
953 | * Retrieves pad format which is active or tried based on requirement | ||
954 | */ | ||
955 | static int tvp514x_get_pad_format(struct v4l2_subdev *sd, | ||
956 | struct v4l2_subdev_fh *fh, | ||
957 | struct v4l2_subdev_format *format) | ||
958 | { | ||
959 | struct tvp514x_decoder *decoder = to_decoder(sd); | ||
960 | __u32 which = format->which; | ||
961 | |||
962 | if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { | ||
963 | format->format = decoder->format; | ||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | format->format.code = V4L2_MBUS_FMT_YUYV8_2X8; | ||
968 | format->format.width = tvp514x_std_list[decoder->current_std].width; | ||
969 | format->format.height = tvp514x_std_list[decoder->current_std].height; | ||
970 | format->format.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
971 | format->format.field = V4L2_FIELD_INTERLACED; | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | /** | ||
977 | * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format | ||
978 | * @sd: pointer to standard V4L2 sub-device structure | ||
979 | * @fh: file handle | ||
980 | * @format: pointer to v4l2_subdev_format structure | ||
981 | * | ||
982 | * Set pad format for the output pad | ||
983 | */ | ||
984 | static int tvp514x_set_pad_format(struct v4l2_subdev *sd, | ||
985 | struct v4l2_subdev_fh *fh, | ||
986 | struct v4l2_subdev_format *fmt) | ||
987 | { | ||
988 | struct tvp514x_decoder *decoder = to_decoder(sd); | ||
989 | |||
990 | if (fmt->format.field != V4L2_FIELD_INTERLACED || | ||
991 | fmt->format.code != V4L2_MBUS_FMT_YUYV8_2X8 || | ||
992 | fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M || | ||
993 | fmt->format.width != tvp514x_std_list[decoder->current_std].width || | ||
994 | fmt->format.height != tvp514x_std_list[decoder->current_std].height) | ||
995 | return -EINVAL; | ||
996 | |||
997 | decoder->format = fmt->format; | ||
998 | |||
999 | return 0; | ||
1000 | } | ||
1001 | |||
895 | static const struct v4l2_subdev_core_ops tvp514x_core_ops = { | 1002 | static const struct v4l2_subdev_core_ops tvp514x_core_ops = { |
896 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, | 1003 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, |
897 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, | 1004 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, |
@@ -915,13 +1022,33 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = { | |||
915 | .s_stream = tvp514x_s_stream, | 1022 | .s_stream = tvp514x_s_stream, |
916 | }; | 1023 | }; |
917 | 1024 | ||
1025 | static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = { | ||
1026 | .enum_mbus_code = tvp514x_enum_mbus_code, | ||
1027 | .get_fmt = tvp514x_get_pad_format, | ||
1028 | .set_fmt = tvp514x_set_pad_format, | ||
1029 | }; | ||
1030 | |||
918 | static const struct v4l2_subdev_ops tvp514x_ops = { | 1031 | static const struct v4l2_subdev_ops tvp514x_ops = { |
919 | .core = &tvp514x_core_ops, | 1032 | .core = &tvp514x_core_ops, |
920 | .video = &tvp514x_video_ops, | 1033 | .video = &tvp514x_video_ops, |
1034 | .pad = &tvp514x_pad_ops, | ||
921 | }; | 1035 | }; |
922 | 1036 | ||
923 | static struct tvp514x_decoder tvp514x_dev = { | 1037 | static struct tvp514x_decoder tvp514x_dev = { |
924 | .streaming = 0, | 1038 | .streaming = 0, |
1039 | .fmt_list = tvp514x_fmt_list, | ||
1040 | .num_fmts = ARRAY_SIZE(tvp514x_fmt_list), | ||
1041 | .pix = { | ||
1042 | /* Default to NTSC 8-bit YUV 422 */ | ||
1043 | .width = NTSC_NUM_ACTIVE_PIXELS, | ||
1044 | .height = NTSC_NUM_ACTIVE_LINES, | ||
1045 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
1046 | .field = V4L2_FIELD_INTERLACED, | ||
1047 | .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2, | ||
1048 | .sizeimage = NTSC_NUM_ACTIVE_PIXELS * 2 * | ||
1049 | NTSC_NUM_ACTIVE_LINES, | ||
1050 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
1051 | }, | ||
925 | .current_std = STD_NTSC_MJ, | 1052 | .current_std = STD_NTSC_MJ, |
926 | .std_list = tvp514x_std_list, | 1053 | .std_list = tvp514x_std_list, |
927 | .num_stds = ARRAY_SIZE(tvp514x_std_list), | 1054 | .num_stds = ARRAY_SIZE(tvp514x_std_list), |
@@ -941,6 +1068,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
941 | { | 1068 | { |
942 | struct tvp514x_decoder *decoder; | 1069 | struct tvp514x_decoder *decoder; |
943 | struct v4l2_subdev *sd; | 1070 | struct v4l2_subdev *sd; |
1071 | int ret; | ||
944 | 1072 | ||
945 | /* Check if the adapter supports the needed features */ | 1073 | /* Check if the adapter supports the needed features */ |
946 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1074 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
@@ -981,7 +1109,21 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
981 | /* Register with V4L2 layer as slave device */ | 1109 | /* Register with V4L2 layer as slave device */ |
982 | sd = &decoder->sd; | 1110 | sd = &decoder->sd; |
983 | v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); | 1111 | v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); |
984 | 1112 | strlcpy(sd->name, TVP514X_MODULE_NAME, sizeof(sd->name)); | |
1113 | |||
1114 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
1115 | decoder->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
1116 | decoder->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
1117 | decoder->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; | ||
1118 | |||
1119 | ret = media_entity_init(&decoder->sd.entity, 1, &decoder->pad, 0); | ||
1120 | if (ret < 0) { | ||
1121 | v4l2_err(sd, "%s decoder driver failed to register !!\n", | ||
1122 | sd->name); | ||
1123 | kfree(decoder); | ||
1124 | return ret; | ||
1125 | } | ||
1126 | #endif | ||
985 | v4l2_ctrl_handler_init(&decoder->hdl, 5); | 1127 | v4l2_ctrl_handler_init(&decoder->hdl, 5); |
986 | v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, | 1128 | v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, |
987 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); | 1129 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); |
@@ -995,10 +1137,10 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
995 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | 1137 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); |
996 | sd->ctrl_handler = &decoder->hdl; | 1138 | sd->ctrl_handler = &decoder->hdl; |
997 | if (decoder->hdl.error) { | 1139 | if (decoder->hdl.error) { |
998 | int err = decoder->hdl.error; | 1140 | ret = decoder->hdl.error; |
999 | 1141 | ||
1000 | v4l2_ctrl_handler_free(&decoder->hdl); | 1142 | v4l2_ctrl_handler_free(&decoder->hdl); |
1001 | return err; | 1143 | return ret; |
1002 | } | 1144 | } |
1003 | v4l2_ctrl_handler_setup(&decoder->hdl); | 1145 | v4l2_ctrl_handler_setup(&decoder->hdl); |
1004 | 1146 | ||
@@ -1021,6 +1163,9 @@ static int tvp514x_remove(struct i2c_client *client) | |||
1021 | struct tvp514x_decoder *decoder = to_decoder(sd); | 1163 | struct tvp514x_decoder *decoder = to_decoder(sd); |
1022 | 1164 | ||
1023 | v4l2_device_unregister_subdev(sd); | 1165 | v4l2_device_unregister_subdev(sd); |
1166 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
1167 | media_entity_cleanup(&decoder->sd.entity); | ||
1168 | #endif | ||
1024 | v4l2_ctrl_handler_free(&decoder->hdl); | 1169 | v4l2_ctrl_handler_free(&decoder->hdl); |
1025 | return 0; | 1170 | return 0; |
1026 | } | 1171 | } |