Message ID | 1447865728-5726-2-git-send-email-l.stach@pengutronix.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Philipp, [auto build test ERROR on: v4.4-rc1] [also build test ERROR on: next-20151118] [cannot apply to: linuxtv-media/master] url: https://github.com/0day-ci/linux/commits/Lucas-Stach/tvp5150-convert-register-access-to-regmap/20151119-005732 config: x86_64-randconfig-x018-11181928 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All error/warnings (new ones prefixed by >>): drivers/media/i2c/tvp5150.c: In function 'tvp5150_get_pad_format': >> drivers/media/i2c/tvp5150.c:1062:10: error: implicit declaration of function 'v4l2_subdev_get_try_format' [-Werror=implicit-function-declaration] return v4l2_subdev_get_try_format(sd, cfg, pad); ^ >> drivers/media/i2c/tvp5150.c:1062:10: warning: return makes pointer from integer without a cast [-Wint-conversion] drivers/media/i2c/tvp5150.c: In function 'tvp5150_get_pad_crop': >> drivers/media/i2c/tvp5150.c:1077:10: error: implicit declaration of function 'v4l2_subdev_get_try_crop' [-Werror=implicit-function-declaration] return v4l2_subdev_get_try_crop(sd, cfg, pad); ^ drivers/media/i2c/tvp5150.c:1077:10: warning: return makes pointer from integer without a cast [-Wint-conversion] drivers/media/i2c/tvp5150.c: In function 'tvp5150_open': >> drivers/media/i2c/tvp5150.c:1180:27: warning: passing argument 2 of 'tvp5150_set_default' makes pointer from integer without a cast [-Wint-conversion] tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0), ^ drivers/media/i2c/tvp5150.c:1152:13: note: expected 'struct v4l2_rect *' but argument is of type 'int' static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop, ^ drivers/media/i2c/tvp5150.c:1181:6: warning: passing argument 3 of 'tvp5150_set_default' makes pointer from integer without a cast [-Wint-conversion] v4l2_subdev_get_try_format(fh, 0)); ^ drivers/media/i2c/tvp5150.c:1152:13: note: expected 'struct v4l2_mbus_framefmt *' but argument is of type 'int' static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop, ^ drivers/media/i2c/tvp5150.c: In function 'tvp5150_probe': >> drivers/media/i2c/tvp5150.c:1340:4: error: 'struct v4l2_subdev' has no member named 'entity' sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; ^ drivers/media/i2c/tvp5150.c:1342:29: error: 'struct v4l2_subdev' has no member named 'entity' res = media_entity_init(&sd->entity, 1, &core->pad, 0); ^ cc1: some warnings being treated as errors vim +/v4l2_subdev_get_try_format +1062 drivers/media/i2c/tvp5150.c 1056 tvp5150_get_pad_format(struct tvp5150 *decoder, struct v4l2_subdev *sd, 1057 struct v4l2_subdev_pad_config *cfg, unsigned int pad, 1058 enum v4l2_subdev_format_whence which) 1059 { 1060 switch (which) { 1061 case V4L2_SUBDEV_FORMAT_TRY: > 1062 return v4l2_subdev_get_try_format(sd, cfg, pad); 1063 case V4L2_SUBDEV_FORMAT_ACTIVE: 1064 return &decoder->format; 1065 default: 1066 return NULL; 1067 } 1068 } 1069 1070 static struct v4l2_rect * 1071 tvp5150_get_pad_crop(struct tvp5150 *decoder, struct v4l2_subdev *sd, 1072 struct v4l2_subdev_pad_config *cfg, unsigned int pad, 1073 enum v4l2_subdev_format_whence which) 1074 { 1075 switch (which) { 1076 case V4L2_SUBDEV_FORMAT_TRY: > 1077 return v4l2_subdev_get_try_crop(sd, cfg, pad); 1078 case V4L2_SUBDEV_FORMAT_ACTIVE: 1079 return &decoder->rect; 1080 default: 1081 return NULL; 1082 } 1083 } 1084 1085 static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, 1086 struct v4l2_subdev_pad_config *cfg, 1087 struct v4l2_subdev_frame_size_enum *fse) 1088 { 1089 struct tvp5150 *decoder = to_tvp5150(sd); 1090 v4l2_std_id std; 1091 1092 if (fse->index > 0 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8) 1093 return -EINVAL; 1094 1095 fse->min_width = TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT; 1096 fse->max_width = TVP5150_H_MAX; 1097 1098 /* Calculate height based on current standard */ 1099 if (decoder->norm == V4L2_STD_ALL) 1100 std = tvp5150_read_std(sd); 1101 else 1102 std = decoder->norm; 1103 1104 if (std & V4L2_STD_525_60) { 1105 fse->min_height = TVP5150_V_MAX_525_60 - TVP5150_MAX_CROP_TOP; 1106 fse->max_height = TVP5150_V_MAX_525_60; 1107 } else { 1108 fse->min_height = TVP5150_V_MAX_OTHERS - TVP5150_MAX_CROP_TOP; 1109 fse->max_height = TVP5150_V_MAX_OTHERS; 1110 } 1111 1112 return 0; 1113 } 1114 1115 static int tvp5150_get_format(struct v4l2_subdev *sd, 1116 struct v4l2_subdev_pad_config *cfg, 1117 struct v4l2_subdev_format *format) 1118 { 1119 struct tvp5150 *decoder = to_tvp5150(sd); 1120 1121 format->format = *tvp5150_get_pad_format(decoder, sd, cfg, 1122 format->pad, format->which); 1123 return 0; 1124 } 1125 1126 static int tvp5150_set_format(struct v4l2_subdev *sd, 1127 struct v4l2_subdev_pad_config *cfg, 1128 struct v4l2_subdev_format *format) 1129 { 1130 struct tvp5150 *decoder = to_tvp5150(sd); 1131 struct v4l2_mbus_framefmt *mbus_format; 1132 struct v4l2_rect *crop; 1133 1134 crop = tvp5150_get_pad_crop(decoder, sd, cfg, format->pad, 1135 format->which); 1136 mbus_format = tvp5150_get_pad_format(decoder, sd, cfg, format->pad, 1137 format->which); 1138 mbus_format->width = crop->width; 1139 mbus_format->height = crop->height; 1140 1141 format->format = *mbus_format; 1142 1143 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) 1144 tvp5150_reset(sd, 0); 1145 1146 v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", mbus_format->width, 1147 mbus_format->height); 1148 1149 return 0; 1150 } 1151 1152 static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop, 1153 struct v4l2_mbus_framefmt *format) 1154 { 1155 crop->left = 0; 1156 crop->width = TVP5150_H_MAX; 1157 crop->top = 0; 1158 if (std & V4L2_STD_525_60) 1159 crop->height = TVP5150_V_MAX_525_60; 1160 else 1161 crop->height = TVP5150_V_MAX_OTHERS; 1162 1163 format->width = crop->width; 1164 format->height = crop->height; 1165 format->code = MEDIA_BUS_FMT_UYVY8_2X8; 1166 format->field = V4L2_FIELD_SEQ_TB; 1167 format->colorspace = V4L2_COLORSPACE_SMPTE170M; 1168 } 1169 1170 static int tvp5150_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1171 { 1172 struct tvp5150 *decoder = to_tvp5150(sd); 1173 v4l2_std_id std; 1174 1175 if (decoder->norm == V4L2_STD_ALL) 1176 std = tvp5150_read_std(sd); 1177 else 1178 std = decoder->norm; 1179 > 1180 tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0), > 1181 v4l2_subdev_get_try_format(fh, 0)); 1182 return 0; 1183 } 1184 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Philipp, [auto build test ERROR on: v4.4-rc1] [also build test ERROR on: next-20151118] [cannot apply to: linuxtv-media/master] url: https://github.com/0day-ci/linux/commits/Lucas-Stach/tvp5150-convert-register-access-to-regmap/20151119-005732 config: x86_64-randconfig-x017-11181928 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64 Note: the linux-review/Lucas-Stach/tvp5150-convert-register-access-to-regmap/20151119-005732 HEAD bda9ffd30fce12dfa1b1964094311ae5dd780461 builds fine. It only hurts bisectibility. All error/warnings (new ones prefixed by >>): drivers/media/i2c/tvp5150.c: In function 'tvp5150_open': >> drivers/media/i2c/tvp5150.c:1180:52: warning: passing argument 1 of 'v4l2_subdev_get_try_crop' from incompatible pointer type [-Wincompatible-pointer-types] tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0), ^ In file included from include/media/v4l2-device.h:25:0, from drivers/media/i2c/tvp5150.c:15: include/media/v4l2-subdev.h:769:37: note: expected 'struct v4l2_subdev *' but argument is of type 'struct v4l2_subdev_fh *' __V4L2_SUBDEV_MK_GET_TRY(v4l2_rect, v4l2_subdev_get_try_crop, try_crop) ^ include/media/v4l2-subdev.h:760:2: note: in definition of macro '__V4L2_SUBDEV_MK_GET_TRY' fun_name(struct v4l2_subdev *sd, \ ^ >> drivers/media/i2c/tvp5150.c:1180:27: error: too few arguments to function 'v4l2_subdev_get_try_crop' tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0), ^ In file included from include/media/v4l2-device.h:25:0, from drivers/media/i2c/tvp5150.c:15: include/media/v4l2-subdev.h:769:37: note: declared here __V4L2_SUBDEV_MK_GET_TRY(v4l2_rect, v4l2_subdev_get_try_crop, try_crop) ^ include/media/v4l2-subdev.h:760:2: note: in definition of macro '__V4L2_SUBDEV_MK_GET_TRY' fun_name(struct v4l2_subdev *sd, \ ^ >> drivers/media/i2c/tvp5150.c:1181:33: warning: passing argument 1 of 'v4l2_subdev_get_try_format' from incompatible pointer type [-Wincompatible-pointer-types] v4l2_subdev_get_try_format(fh, 0)); ^ In file included from include/media/v4l2-device.h:25:0, from drivers/media/i2c/tvp5150.c:15: include/media/v4l2-subdev.h:768:46: note: expected 'struct v4l2_subdev *' but argument is of type 'struct v4l2_subdev_fh *' __V4L2_SUBDEV_MK_GET_TRY(v4l2_mbus_framefmt, v4l2_subdev_get_try_format, try_fmt) ^ include/media/v4l2-subdev.h:760:2: note: in definition of macro '__V4L2_SUBDEV_MK_GET_TRY' fun_name(struct v4l2_subdev *sd, \ ^ >> drivers/media/i2c/tvp5150.c:1181:6: error: too few arguments to function 'v4l2_subdev_get_try_format' v4l2_subdev_get_try_format(fh, 0)); ^ In file included from include/media/v4l2-device.h:25:0, from drivers/media/i2c/tvp5150.c:15: include/media/v4l2-subdev.h:768:46: note: declared here __V4L2_SUBDEV_MK_GET_TRY(v4l2_mbus_framefmt, v4l2_subdev_get_try_format, try_fmt) ^ include/media/v4l2-subdev.h:760:2: note: in definition of macro '__V4L2_SUBDEV_MK_GET_TRY' fun_name(struct v4l2_subdev *sd, \ ^ vim +/v4l2_subdev_get_try_crop +1180 drivers/media/i2c/tvp5150.c 1174 1175 if (decoder->norm == V4L2_STD_ALL) 1176 std = tvp5150_read_std(sd); 1177 else 1178 std = decoder->norm; 1179 > 1180 tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0), > 1181 v4l2_subdev_get_try_format(fh, 0)); 1182 return 0; 1183 } 1184 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Am Donnerstag, den 19.11.2015, 01:06 +0800 schrieb kbuild test robot: > Hi Philipp, > > [auto build test ERROR on: v4.4-rc1] > [also build test ERROR on: next-20151118] > [cannot apply to: linuxtv-media/master] > > url: https://github.com/0day-ci/linux/commits/Lucas-Stach/tvp5150-convert-register-access-to-regmap/20151119-005732 > config: x86_64-randconfig-x018-11181928 (attached as .config) > reproduce: > # save the attached .config to linux build tree > make ARCH=x86_64 > > All error/warnings (new ones prefixed by >>): > > drivers/media/i2c/tvp5150.c: In function 'tvp5150_get_pad_format': > >> drivers/media/i2c/tvp5150.c:1062:10: error: implicit declaration of function 'v4l2_subdev_get_try_format' [-Werror=implicit-function-declaration] > return v4l2_subdev_get_try_format(sd, cfg, pad); > ^ > >> drivers/media/i2c/tvp5150.c:1062:10: warning: return makes pointer from integer without a cast [-Wint-conversion] > drivers/media/i2c/tvp5150.c: In function 'tvp5150_get_pad_crop': > >> drivers/media/i2c/tvp5150.c:1077:10: error: implicit declaration of function 'v4l2_subdev_get_try_crop' [-Werror=implicit-function-declaration] > return v4l2_subdev_get_try_crop(sd, cfg, pad); > ^ > drivers/media/i2c/tvp5150.c:1077:10: warning: return makes pointer from integer without a cast [-Wint-conversion] > drivers/media/i2c/tvp5150.c: In function 'tvp5150_open': > >> drivers/media/i2c/tvp5150.c:1180:27: warning: passing argument 2 of 'tvp5150_set_default' makes pointer from integer without a cast [-Wint-conversion] > tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0), > ^ > drivers/media/i2c/tvp5150.c:1152:13: note: expected 'struct v4l2_rect *' but argument is of type 'int' > static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop, > ^ > drivers/media/i2c/tvp5150.c:1181:6: warning: passing argument 3 of 'tvp5150_set_default' makes pointer from integer without a cast [-Wint-conversion] > v4l2_subdev_get_try_format(fh, 0)); > ^ > drivers/media/i2c/tvp5150.c:1152:13: note: expected 'struct v4l2_mbus_framefmt *' but argument is of type 'int' > static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop, > ^ > drivers/media/i2c/tvp5150.c: In function 'tvp5150_probe': > >> drivers/media/i2c/tvp5150.c:1340:4: error: 'struct v4l2_subdev' has no member named 'entity' > sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; > ^ > drivers/media/i2c/tvp5150.c:1342:29: error: 'struct v4l2_subdev' has no member named 'entity' > res = media_entity_init(&sd->entity, 1, &core->pad, 0); > ^ > cc1: some warnings being treated as errors Ok, this is just a missing depends on VIDEO_V4L2_SUBDEV_API. I'll wait for other feedback before resending with that fixed. Regards, Lucas
Em Thu, 19 Nov 2015 09:59:15 +0100 Lucas Stach <l.stach@pengutronix.de> escreveu: > Am Donnerstag, den 19.11.2015, 01:06 +0800 schrieb kbuild test robot: > > Hi Philipp, > > > > [auto build test ERROR on: v4.4-rc1] > > [also build test ERROR on: next-20151118] > > [cannot apply to: linuxtv-media/master] > > > > url: https://github.com/0day-ci/linux/commits/Lucas-Stach/tvp5150-convert-register-access-to-regmap/20151119-005732 > > config: x86_64-randconfig-x018-11181928 (attached as .config) > > reproduce: > > # save the attached .config to linux build tree > > make ARCH=x86_64 > > > > All error/warnings (new ones prefixed by >>): > > > > drivers/media/i2c/tvp5150.c: In function 'tvp5150_get_pad_format': > > >> drivers/media/i2c/tvp5150.c:1062:10: error: implicit declaration of function 'v4l2_subdev_get_try_format' [-Werror=implicit-function-declaration] > > return v4l2_subdev_get_try_format(sd, cfg, pad); > > ^ > > >> drivers/media/i2c/tvp5150.c:1062:10: warning: return makes pointer from integer without a cast [-Wint-conversion] > > drivers/media/i2c/tvp5150.c: In function 'tvp5150_get_pad_crop': > > >> drivers/media/i2c/tvp5150.c:1077:10: error: implicit declaration of function 'v4l2_subdev_get_try_crop' [-Werror=implicit-function-declaration] > > return v4l2_subdev_get_try_crop(sd, cfg, pad); > > ^ > > drivers/media/i2c/tvp5150.c:1077:10: warning: return makes pointer from integer without a cast [-Wint-conversion] > > drivers/media/i2c/tvp5150.c: In function 'tvp5150_open': > > >> drivers/media/i2c/tvp5150.c:1180:27: warning: passing argument 2 of 'tvp5150_set_default' makes pointer from integer without a cast [-Wint-conversion] > > tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0), > > ^ > > drivers/media/i2c/tvp5150.c:1152:13: note: expected 'struct v4l2_rect *' but argument is of type 'int' > > static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop, > > ^ > > drivers/media/i2c/tvp5150.c:1181:6: warning: passing argument 3 of 'tvp5150_set_default' makes pointer from integer without a cast [-Wint-conversion] > > v4l2_subdev_get_try_format(fh, 0)); > > ^ > > drivers/media/i2c/tvp5150.c:1152:13: note: expected 'struct v4l2_mbus_framefmt *' but argument is of type 'int' > > static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop, > > ^ > > drivers/media/i2c/tvp5150.c: In function 'tvp5150_probe': > > >> drivers/media/i2c/tvp5150.c:1340:4: error: 'struct v4l2_subdev' has no member named 'entity' > > sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; > > ^ > > drivers/media/i2c/tvp5150.c:1342:29: error: 'struct v4l2_subdev' has no member named 'entity' > > res = media_entity_init(&sd->entity, 1, &core->pad, 0); > > ^ > > cc1: some warnings being treated as errors > > Ok, this is just a missing depends on VIDEO_V4L2_SUBDEV_API. I'll wait > for other feedback before resending with that fixed. Lucas, Please notice that tvp5150 is used by drivers that doesn't need nor want VIDEO_V4L2_SUBDEV_API. So, you should be sure that the driver will compile fine without subdev API, and will keep working properly for those devices, no matter if subdev API was compiled or not. Regards, Mauro -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index a7495d2856c3..8670b478dcd6 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -36,7 +36,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct tvp5150 { struct v4l2_subdev sd; + struct media_pad pad; struct v4l2_ctrl_handler hdl; + struct v4l2_mbus_framefmt format; struct v4l2_rect rect; struct regmap *regmap; @@ -819,38 +821,68 @@ static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, return 0; } -static int tvp5150_fill_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *format) +static void tvp5150_try_crop(struct tvp5150 *decoder, struct v4l2_rect *rect, + v4l2_std_id std) { - struct v4l2_mbus_framefmt *f; - struct tvp5150 *decoder = to_tvp5150(sd); + unsigned int hmax; - if (!format || format->pad) - return -EINVAL; + /* Clamp the crop rectangle boundaries to tvp5150 limits */ + rect->left = clamp(rect->left, 0, TVP5150_MAX_CROP_LEFT); + rect->width = clamp(rect->width, + TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect->left, + TVP5150_H_MAX - rect->left); + rect->top = clamp(rect->top, 0, TVP5150_MAX_CROP_TOP); - f = &format->format; + /* tvp5150 has some special limits */ + rect->left = clamp(rect->left, 0, TVP5150_MAX_CROP_LEFT); + rect->width = clamp_t(unsigned int, rect->width, + TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect->left, + TVP5150_H_MAX - rect->left); + rect->top = clamp(rect->top, 0, TVP5150_MAX_CROP_TOP); - tvp5150_reset(sd, 0); + /* Calculate height based on current standard */ + if (std & V4L2_STD_525_60) + hmax = TVP5150_V_MAX_525_60; + else + hmax = TVP5150_V_MAX_OTHERS; - f->width = decoder->rect.width; - f->height = decoder->rect.height; + rect->height = clamp(rect->height, + hmax - TVP5150_MAX_CROP_TOP - rect->top, + hmax - rect->top); +} - f->code = MEDIA_BUS_FMT_UYVY8_2X8; - f->field = V4L2_FIELD_SEQ_TB; - f->colorspace = V4L2_COLORSPACE_SMPTE170M; +static void tvp5150_set_crop(struct tvp5150 *decoder, struct v4l2_rect *rect, + v4l2_std_id std) +{ + struct regmap *map = decoder->regmap; + unsigned int hmax; - v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width, - f->height); - return 0; + if (std & V4L2_STD_525_60) + hmax = TVP5150_V_MAX_525_60; + else + hmax = TVP5150_V_MAX_OTHERS; + + regmap_write(map, TVP5150_VERT_BLANKING_START, rect->top); + regmap_write(map, TVP5150_VERT_BLANKING_STOP, + rect->top + rect->height - hmax); + regmap_write(map, TVP5150_ACT_VD_CROP_ST_MSB, + rect->left >> TVP5150_CROP_SHIFT); + regmap_write(map, TVP5150_ACT_VD_CROP_ST_LSB, + rect->left | (1 << TVP5150_CROP_SHIFT)); + regmap_write(map, TVP5150_ACT_VD_CROP_STP_MSB, + (rect->left + rect->width - TVP5150_MAX_CROP_LEFT) >> + TVP5150_CROP_SHIFT); + regmap_write(map, TVP5150_ACT_VD_CROP_STP_LSB, + rect->left + rect->width - TVP5150_MAX_CROP_LEFT); + + decoder->rect = *rect; } static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { - struct v4l2_rect rect = a->c; struct tvp5150 *decoder = to_tvp5150(sd); + struct v4l2_rect rect = a->c; v4l2_std_id std; - unsigned int hmax; v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n", __func__, rect.left, rect.top, rect.width, rect.height); @@ -858,42 +890,13 @@ static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - /* tvp5150 has some special limits */ - rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); - rect.width = clamp_t(unsigned int, rect.width, - TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, - TVP5150_H_MAX - rect.left); - rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP); - - /* Calculate height based on current standard */ if (decoder->norm == V4L2_STD_ALL) std = tvp5150_read_std(sd); else std = decoder->norm; - if (std & V4L2_STD_525_60) - hmax = TVP5150_V_MAX_525_60; - else - hmax = TVP5150_V_MAX_OTHERS; - - rect.height = clamp_t(unsigned int, rect.height, - hmax - TVP5150_MAX_CROP_TOP - rect.top, - hmax - rect.top); - - regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top); - regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP, - rect.top + rect.height - hmax); - regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB, - rect.left >> TVP5150_CROP_SHIFT); - regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB, - rect.left | (1 << TVP5150_CROP_SHIFT)); - regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB, - (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> - TVP5150_CROP_SHIFT); - regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB, - rect.left + rect.width - TVP5150_MAX_CROP_LEFT); - - decoder->rect = rect; + tvp5150_try_crop(decoder, &rect, std); + tvp5150_set_crop(decoder, &rect, std); return 0; } @@ -1049,6 +1052,138 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) /* ----------------------------------------------------------------------- */ +static struct v4l2_mbus_framefmt * +tvp5150_get_pad_format(struct tvp5150 *decoder, struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, unsigned int pad, + enum v4l2_subdev_format_whence which) +{ + switch (which) { + case V4L2_SUBDEV_FORMAT_TRY: + return v4l2_subdev_get_try_format(sd, cfg, pad); + case V4L2_SUBDEV_FORMAT_ACTIVE: + return &decoder->format; + default: + return NULL; + } +} + +static struct v4l2_rect * +tvp5150_get_pad_crop(struct tvp5150 *decoder, struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, unsigned int pad, + enum v4l2_subdev_format_whence which) +{ + switch (which) { + case V4L2_SUBDEV_FORMAT_TRY: + return v4l2_subdev_get_try_crop(sd, cfg, pad); + case V4L2_SUBDEV_FORMAT_ACTIVE: + return &decoder->rect; + default: + return NULL; + } +} + +static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + v4l2_std_id std; + + if (fse->index > 0 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8) + return -EINVAL; + + fse->min_width = TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT; + fse->max_width = TVP5150_H_MAX; + + /* Calculate height based on current standard */ + if (decoder->norm == V4L2_STD_ALL) + std = tvp5150_read_std(sd); + else + std = decoder->norm; + + if (std & V4L2_STD_525_60) { + fse->min_height = TVP5150_V_MAX_525_60 - TVP5150_MAX_CROP_TOP; + fse->max_height = TVP5150_V_MAX_525_60; + } else { + fse->min_height = TVP5150_V_MAX_OTHERS - TVP5150_MAX_CROP_TOP; + fse->max_height = TVP5150_V_MAX_OTHERS; + } + + return 0; +} + +static int tvp5150_get_format(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + + format->format = *tvp5150_get_pad_format(decoder, sd, cfg, + format->pad, format->which); + return 0; +} + +static int tvp5150_set_format(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + struct v4l2_mbus_framefmt *mbus_format; + struct v4l2_rect *crop; + + crop = tvp5150_get_pad_crop(decoder, sd, cfg, format->pad, + format->which); + mbus_format = tvp5150_get_pad_format(decoder, sd, cfg, format->pad, + format->which); + mbus_format->width = crop->width; + mbus_format->height = crop->height; + + format->format = *mbus_format; + + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) + tvp5150_reset(sd, 0); + + v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", mbus_format->width, + mbus_format->height); + + return 0; +} + +static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop, + struct v4l2_mbus_framefmt *format) +{ + crop->left = 0; + crop->width = TVP5150_H_MAX; + crop->top = 0; + if (std & V4L2_STD_525_60) + crop->height = TVP5150_V_MAX_525_60; + else + crop->height = TVP5150_V_MAX_OTHERS; + + format->width = crop->width; + format->height = crop->height; + format->code = MEDIA_BUS_FMT_UYVY8_2X8; + format->field = V4L2_FIELD_SEQ_TB; + format->colorspace = V4L2_COLORSPACE_SMPTE170M; +} + +static int tvp5150_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + v4l2_std_id std; + + if (decoder->norm == V4L2_STD_ALL) + std = tvp5150_read_std(sd); + else + std = decoder->norm; + + tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0), + v4l2_subdev_get_try_format(fh, 0)); + return 0; +} + +/* ----------------------------------------------------------------------- */ + static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = { .s_ctrl = tvp5150_s_ctrl, }; @@ -1083,8 +1218,9 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { 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, + .enum_frame_size = tvp5150_enum_frame_size, + .get_fmt = tvp5150_get_format, + .set_fmt = tvp5150_set_format, }; static const struct v4l2_subdev_ops tvp5150_ops = { @@ -1095,6 +1231,9 @@ static const struct v4l2_subdev_ops tvp5150_ops = { .pad = &tvp5150_pad_ops, }; +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = { + .open = tvp5150_open, +}; /**************************************************************************** I2C Client & Driver @@ -1196,6 +1335,13 @@ static int tvp5150_probe(struct i2c_client *c, core->regmap = map; sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); + sd->internal_ops = &tvp5150_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; + core->pad.flags = MEDIA_PAD_FL_SOURCE; + res = media_entity_init(&sd->entity, 1, &core->pad, 0); + if (res < 0) + return res; /* * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID, @@ -1250,14 +1396,9 @@ static int tvp5150_probe(struct i2c_client *c, v4l2_ctrl_handler_setup(&core->hdl); /* Default is no cropping */ - core->rect.top = 0; - if (tvp5150_read_std(sd) & V4L2_STD_525_60) - core->rect.height = TVP5150_V_MAX_525_60; - else - core->rect.height = TVP5150_V_MAX_OTHERS; - core->rect.left = 0; - core->rect.width = TVP5150_H_MAX; + tvp5150_set_default(tvp5150_read_std(sd), &core->rect, &core->format); + sd->dev = &c->dev; res = v4l2_async_register_subdev(sd); if (res < 0) goto err;