0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/types.h>
0010 #include <linux/kernel.h>
0011 #include <linux/errno.h>
0012 #include <linux/rational.h>
0013 #include <linux/videodev2.h>
0014 #include <linux/v4l2-dv-timings.h>
0015 #include <media/v4l2-dv-timings.h>
0016 #include <linux/math64.h>
0017 #include <linux/hdmi.h>
0018 #include <media/cec.h>
0019
0020 MODULE_AUTHOR("Hans Verkuil");
0021 MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions");
0022 MODULE_LICENSE("GPL");
0023
0024 const struct v4l2_dv_timings v4l2_dv_timings_presets[] = {
0025 V4L2_DV_BT_CEA_640X480P59_94,
0026 V4L2_DV_BT_CEA_720X480I59_94,
0027 V4L2_DV_BT_CEA_720X480P59_94,
0028 V4L2_DV_BT_CEA_720X576I50,
0029 V4L2_DV_BT_CEA_720X576P50,
0030 V4L2_DV_BT_CEA_1280X720P24,
0031 V4L2_DV_BT_CEA_1280X720P25,
0032 V4L2_DV_BT_CEA_1280X720P30,
0033 V4L2_DV_BT_CEA_1280X720P50,
0034 V4L2_DV_BT_CEA_1280X720P60,
0035 V4L2_DV_BT_CEA_1920X1080P24,
0036 V4L2_DV_BT_CEA_1920X1080P25,
0037 V4L2_DV_BT_CEA_1920X1080P30,
0038 V4L2_DV_BT_CEA_1920X1080I50,
0039 V4L2_DV_BT_CEA_1920X1080P50,
0040 V4L2_DV_BT_CEA_1920X1080I60,
0041 V4L2_DV_BT_CEA_1920X1080P60,
0042 V4L2_DV_BT_DMT_640X350P85,
0043 V4L2_DV_BT_DMT_640X400P85,
0044 V4L2_DV_BT_DMT_720X400P85,
0045 V4L2_DV_BT_DMT_640X480P72,
0046 V4L2_DV_BT_DMT_640X480P75,
0047 V4L2_DV_BT_DMT_640X480P85,
0048 V4L2_DV_BT_DMT_800X600P56,
0049 V4L2_DV_BT_DMT_800X600P60,
0050 V4L2_DV_BT_DMT_800X600P72,
0051 V4L2_DV_BT_DMT_800X600P75,
0052 V4L2_DV_BT_DMT_800X600P85,
0053 V4L2_DV_BT_DMT_800X600P120_RB,
0054 V4L2_DV_BT_DMT_848X480P60,
0055 V4L2_DV_BT_DMT_1024X768I43,
0056 V4L2_DV_BT_DMT_1024X768P60,
0057 V4L2_DV_BT_DMT_1024X768P70,
0058 V4L2_DV_BT_DMT_1024X768P75,
0059 V4L2_DV_BT_DMT_1024X768P85,
0060 V4L2_DV_BT_DMT_1024X768P120_RB,
0061 V4L2_DV_BT_DMT_1152X864P75,
0062 V4L2_DV_BT_DMT_1280X768P60_RB,
0063 V4L2_DV_BT_DMT_1280X768P60,
0064 V4L2_DV_BT_DMT_1280X768P75,
0065 V4L2_DV_BT_DMT_1280X768P85,
0066 V4L2_DV_BT_DMT_1280X768P120_RB,
0067 V4L2_DV_BT_DMT_1280X800P60_RB,
0068 V4L2_DV_BT_DMT_1280X800P60,
0069 V4L2_DV_BT_DMT_1280X800P75,
0070 V4L2_DV_BT_DMT_1280X800P85,
0071 V4L2_DV_BT_DMT_1280X800P120_RB,
0072 V4L2_DV_BT_DMT_1280X960P60,
0073 V4L2_DV_BT_DMT_1280X960P85,
0074 V4L2_DV_BT_DMT_1280X960P120_RB,
0075 V4L2_DV_BT_DMT_1280X1024P60,
0076 V4L2_DV_BT_DMT_1280X1024P75,
0077 V4L2_DV_BT_DMT_1280X1024P85,
0078 V4L2_DV_BT_DMT_1280X1024P120_RB,
0079 V4L2_DV_BT_DMT_1360X768P60,
0080 V4L2_DV_BT_DMT_1360X768P120_RB,
0081 V4L2_DV_BT_DMT_1366X768P60,
0082 V4L2_DV_BT_DMT_1366X768P60_RB,
0083 V4L2_DV_BT_DMT_1400X1050P60_RB,
0084 V4L2_DV_BT_DMT_1400X1050P60,
0085 V4L2_DV_BT_DMT_1400X1050P75,
0086 V4L2_DV_BT_DMT_1400X1050P85,
0087 V4L2_DV_BT_DMT_1400X1050P120_RB,
0088 V4L2_DV_BT_DMT_1440X900P60_RB,
0089 V4L2_DV_BT_DMT_1440X900P60,
0090 V4L2_DV_BT_DMT_1440X900P75,
0091 V4L2_DV_BT_DMT_1440X900P85,
0092 V4L2_DV_BT_DMT_1440X900P120_RB,
0093 V4L2_DV_BT_DMT_1600X900P60_RB,
0094 V4L2_DV_BT_DMT_1600X1200P60,
0095 V4L2_DV_BT_DMT_1600X1200P65,
0096 V4L2_DV_BT_DMT_1600X1200P70,
0097 V4L2_DV_BT_DMT_1600X1200P75,
0098 V4L2_DV_BT_DMT_1600X1200P85,
0099 V4L2_DV_BT_DMT_1600X1200P120_RB,
0100 V4L2_DV_BT_DMT_1680X1050P60_RB,
0101 V4L2_DV_BT_DMT_1680X1050P60,
0102 V4L2_DV_BT_DMT_1680X1050P75,
0103 V4L2_DV_BT_DMT_1680X1050P85,
0104 V4L2_DV_BT_DMT_1680X1050P120_RB,
0105 V4L2_DV_BT_DMT_1792X1344P60,
0106 V4L2_DV_BT_DMT_1792X1344P75,
0107 V4L2_DV_BT_DMT_1792X1344P120_RB,
0108 V4L2_DV_BT_DMT_1856X1392P60,
0109 V4L2_DV_BT_DMT_1856X1392P75,
0110 V4L2_DV_BT_DMT_1856X1392P120_RB,
0111 V4L2_DV_BT_DMT_1920X1200P60_RB,
0112 V4L2_DV_BT_DMT_1920X1200P60,
0113 V4L2_DV_BT_DMT_1920X1200P75,
0114 V4L2_DV_BT_DMT_1920X1200P85,
0115 V4L2_DV_BT_DMT_1920X1200P120_RB,
0116 V4L2_DV_BT_DMT_1920X1440P60,
0117 V4L2_DV_BT_DMT_1920X1440P75,
0118 V4L2_DV_BT_DMT_1920X1440P120_RB,
0119 V4L2_DV_BT_DMT_2048X1152P60_RB,
0120 V4L2_DV_BT_DMT_2560X1600P60_RB,
0121 V4L2_DV_BT_DMT_2560X1600P60,
0122 V4L2_DV_BT_DMT_2560X1600P75,
0123 V4L2_DV_BT_DMT_2560X1600P85,
0124 V4L2_DV_BT_DMT_2560X1600P120_RB,
0125 V4L2_DV_BT_CEA_3840X2160P24,
0126 V4L2_DV_BT_CEA_3840X2160P25,
0127 V4L2_DV_BT_CEA_3840X2160P30,
0128 V4L2_DV_BT_CEA_3840X2160P50,
0129 V4L2_DV_BT_CEA_3840X2160P60,
0130 V4L2_DV_BT_CEA_4096X2160P24,
0131 V4L2_DV_BT_CEA_4096X2160P25,
0132 V4L2_DV_BT_CEA_4096X2160P30,
0133 V4L2_DV_BT_CEA_4096X2160P50,
0134 V4L2_DV_BT_DMT_4096X2160P59_94_RB,
0135 V4L2_DV_BT_CEA_4096X2160P60,
0136 { }
0137 };
0138 EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
0139
0140 bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t,
0141 const struct v4l2_dv_timings_cap *dvcap,
0142 v4l2_check_dv_timings_fnc fnc,
0143 void *fnc_handle)
0144 {
0145 const struct v4l2_bt_timings *bt = &t->bt;
0146 const struct v4l2_bt_timings_cap *cap = &dvcap->bt;
0147 u32 caps = cap->capabilities;
0148
0149 if (t->type != V4L2_DV_BT_656_1120)
0150 return false;
0151 if (t->type != dvcap->type ||
0152 bt->height < cap->min_height ||
0153 bt->height > cap->max_height ||
0154 bt->width < cap->min_width ||
0155 bt->width > cap->max_width ||
0156 bt->pixelclock < cap->min_pixelclock ||
0157 bt->pixelclock > cap->max_pixelclock ||
0158 (!(caps & V4L2_DV_BT_CAP_CUSTOM) &&
0159 cap->standards && bt->standards &&
0160 !(bt->standards & cap->standards)) ||
0161 (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) ||
0162 (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE)))
0163 return false;
0164 return fnc == NULL || fnc(t, fnc_handle);
0165 }
0166 EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings);
0167
0168 int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t,
0169 const struct v4l2_dv_timings_cap *cap,
0170 v4l2_check_dv_timings_fnc fnc,
0171 void *fnc_handle)
0172 {
0173 u32 i, idx;
0174
0175 memset(t->reserved, 0, sizeof(t->reserved));
0176 for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
0177 if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
0178 fnc, fnc_handle) &&
0179 idx++ == t->index) {
0180 t->timings = v4l2_dv_timings_presets[i];
0181 return 0;
0182 }
0183 }
0184 return -EINVAL;
0185 }
0186 EXPORT_SYMBOL_GPL(v4l2_enum_dv_timings_cap);
0187
0188 bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t,
0189 const struct v4l2_dv_timings_cap *cap,
0190 unsigned pclock_delta,
0191 v4l2_check_dv_timings_fnc fnc,
0192 void *fnc_handle)
0193 {
0194 int i;
0195
0196 if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle))
0197 return false;
0198
0199 for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
0200 if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
0201 fnc, fnc_handle) &&
0202 v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i,
0203 pclock_delta, false)) {
0204 u32 flags = t->bt.flags & V4L2_DV_FL_REDUCED_FPS;
0205
0206 *t = v4l2_dv_timings_presets[i];
0207 if (can_reduce_fps(&t->bt))
0208 t->bt.flags |= flags;
0209
0210 return true;
0211 }
0212 }
0213 return false;
0214 }
0215 EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cap);
0216
0217 bool v4l2_find_dv_timings_cea861_vic(struct v4l2_dv_timings *t, u8 vic)
0218 {
0219 unsigned int i;
0220
0221 for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
0222 const struct v4l2_bt_timings *bt =
0223 &v4l2_dv_timings_presets[i].bt;
0224
0225 if ((bt->flags & V4L2_DV_FL_HAS_CEA861_VIC) &&
0226 bt->cea861_vic == vic) {
0227 *t = v4l2_dv_timings_presets[i];
0228 return true;
0229 }
0230 }
0231 return false;
0232 }
0233 EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cea861_vic);
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245 bool v4l2_match_dv_timings(const struct v4l2_dv_timings *t1,
0246 const struct v4l2_dv_timings *t2,
0247 unsigned pclock_delta, bool match_reduced_fps)
0248 {
0249 if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120)
0250 return false;
0251 if (t1->bt.width == t2->bt.width &&
0252 t1->bt.height == t2->bt.height &&
0253 t1->bt.interlaced == t2->bt.interlaced &&
0254 t1->bt.polarities == t2->bt.polarities &&
0255 t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta &&
0256 t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta &&
0257 t1->bt.hfrontporch == t2->bt.hfrontporch &&
0258 t1->bt.hsync == t2->bt.hsync &&
0259 t1->bt.hbackporch == t2->bt.hbackporch &&
0260 t1->bt.vfrontporch == t2->bt.vfrontporch &&
0261 t1->bt.vsync == t2->bt.vsync &&
0262 t1->bt.vbackporch == t2->bt.vbackporch &&
0263 (!match_reduced_fps ||
0264 (t1->bt.flags & V4L2_DV_FL_REDUCED_FPS) ==
0265 (t2->bt.flags & V4L2_DV_FL_REDUCED_FPS)) &&
0266 (!t1->bt.interlaced ||
0267 (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch &&
0268 t1->bt.il_vsync == t2->bt.il_vsync &&
0269 t1->bt.il_vbackporch == t2->bt.il_vbackporch)))
0270 return true;
0271 return false;
0272 }
0273 EXPORT_SYMBOL_GPL(v4l2_match_dv_timings);
0274
0275 void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix,
0276 const struct v4l2_dv_timings *t, bool detailed)
0277 {
0278 const struct v4l2_bt_timings *bt = &t->bt;
0279 u32 htot, vtot;
0280 u32 fps;
0281
0282 if (t->type != V4L2_DV_BT_656_1120)
0283 return;
0284
0285 htot = V4L2_DV_BT_FRAME_WIDTH(bt);
0286 vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
0287 if (bt->interlaced)
0288 vtot /= 2;
0289
0290 fps = (htot * vtot) > 0 ? div_u64((100 * (u64)bt->pixelclock),
0291 (htot * vtot)) : 0;
0292
0293 if (prefix == NULL)
0294 prefix = "";
0295
0296 pr_info("%s: %s%ux%u%s%u.%02u (%ux%u)\n", dev_prefix, prefix,
0297 bt->width, bt->height, bt->interlaced ? "i" : "p",
0298 fps / 100, fps % 100, htot, vtot);
0299
0300 if (!detailed)
0301 return;
0302
0303 pr_info("%s: horizontal: fp = %u, %ssync = %u, bp = %u\n",
0304 dev_prefix, bt->hfrontporch,
0305 (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-",
0306 bt->hsync, bt->hbackporch);
0307 pr_info("%s: vertical: fp = %u, %ssync = %u, bp = %u\n",
0308 dev_prefix, bt->vfrontporch,
0309 (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
0310 bt->vsync, bt->vbackporch);
0311 if (bt->interlaced)
0312 pr_info("%s: vertical bottom field: fp = %u, %ssync = %u, bp = %u\n",
0313 dev_prefix, bt->il_vfrontporch,
0314 (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
0315 bt->il_vsync, bt->il_vbackporch);
0316 pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock);
0317 pr_info("%s: flags (0x%x):%s%s%s%s%s%s%s%s%s%s\n",
0318 dev_prefix, bt->flags,
0319 (bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ?
0320 " REDUCED_BLANKING" : "",
0321 ((bt->flags & V4L2_DV_FL_REDUCED_BLANKING) &&
0322 bt->vsync == 8) ? " (V2)" : "",
0323 (bt->flags & V4L2_DV_FL_CAN_REDUCE_FPS) ?
0324 " CAN_REDUCE_FPS" : "",
0325 (bt->flags & V4L2_DV_FL_REDUCED_FPS) ?
0326 " REDUCED_FPS" : "",
0327 (bt->flags & V4L2_DV_FL_HALF_LINE) ?
0328 " HALF_LINE" : "",
0329 (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) ?
0330 " CE_VIDEO" : "",
0331 (bt->flags & V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE) ?
0332 " FIRST_FIELD_EXTRA_LINE" : "",
0333 (bt->flags & V4L2_DV_FL_HAS_PICTURE_ASPECT) ?
0334 " HAS_PICTURE_ASPECT" : "",
0335 (bt->flags & V4L2_DV_FL_HAS_CEA861_VIC) ?
0336 " HAS_CEA861_VIC" : "",
0337 (bt->flags & V4L2_DV_FL_HAS_HDMI_VIC) ?
0338 " HAS_HDMI_VIC" : "");
0339 pr_info("%s: standards (0x%x):%s%s%s%s%s\n", dev_prefix, bt->standards,
0340 (bt->standards & V4L2_DV_BT_STD_CEA861) ? " CEA" : "",
0341 (bt->standards & V4L2_DV_BT_STD_DMT) ? " DMT" : "",
0342 (bt->standards & V4L2_DV_BT_STD_CVT) ? " CVT" : "",
0343 (bt->standards & V4L2_DV_BT_STD_GTF) ? " GTF" : "",
0344 (bt->standards & V4L2_DV_BT_STD_SDI) ? " SDI" : "");
0345 if (bt->flags & V4L2_DV_FL_HAS_PICTURE_ASPECT)
0346 pr_info("%s: picture aspect (hor:vert): %u:%u\n", dev_prefix,
0347 bt->picture_aspect.numerator,
0348 bt->picture_aspect.denominator);
0349 if (bt->flags & V4L2_DV_FL_HAS_CEA861_VIC)
0350 pr_info("%s: CEA-861 VIC: %u\n", dev_prefix, bt->cea861_vic);
0351 if (bt->flags & V4L2_DV_FL_HAS_HDMI_VIC)
0352 pr_info("%s: HDMI VIC: %u\n", dev_prefix, bt->hdmi_vic);
0353 }
0354 EXPORT_SYMBOL_GPL(v4l2_print_dv_timings);
0355
0356 struct v4l2_fract v4l2_dv_timings_aspect_ratio(const struct v4l2_dv_timings *t)
0357 {
0358 struct v4l2_fract ratio = { 1, 1 };
0359 unsigned long n, d;
0360
0361 if (t->type != V4L2_DV_BT_656_1120)
0362 return ratio;
0363 if (!(t->bt.flags & V4L2_DV_FL_HAS_PICTURE_ASPECT))
0364 return ratio;
0365
0366 ratio.numerator = t->bt.width * t->bt.picture_aspect.denominator;
0367 ratio.denominator = t->bt.height * t->bt.picture_aspect.numerator;
0368
0369 rational_best_approximation(ratio.numerator, ratio.denominator,
0370 ratio.numerator, ratio.denominator, &n, &d);
0371 ratio.numerator = n;
0372 ratio.denominator = d;
0373 return ratio;
0374 }
0375 EXPORT_SYMBOL_GPL(v4l2_dv_timings_aspect_ratio);
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 struct v4l2_fract v4l2_calc_timeperframe(const struct v4l2_dv_timings *t)
0386 {
0387 const struct v4l2_bt_timings *bt = &t->bt;
0388 struct v4l2_fract fps_fract = { 1, 1 };
0389 unsigned long n, d;
0390 u32 htot, vtot, fps;
0391 u64 pclk;
0392
0393 if (t->type != V4L2_DV_BT_656_1120)
0394 return fps_fract;
0395
0396 htot = V4L2_DV_BT_FRAME_WIDTH(bt);
0397 vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
0398 pclk = bt->pixelclock;
0399
0400 if ((bt->flags & V4L2_DV_FL_CAN_DETECT_REDUCED_FPS) &&
0401 (bt->flags & V4L2_DV_FL_REDUCED_FPS))
0402 pclk = div_u64(pclk * 1000ULL, 1001);
0403
0404 fps = (htot * vtot) > 0 ? div_u64((100 * pclk), (htot * vtot)) : 0;
0405 if (!fps)
0406 return fps_fract;
0407
0408 rational_best_approximation(fps, 100, fps, 100, &n, &d);
0409
0410 fps_fract.numerator = d;
0411 fps_fract.denominator = n;
0412 return fps_fract;
0413 }
0414 EXPORT_SYMBOL_GPL(v4l2_calc_timeperframe);
0415
0416
0417
0418
0419
0420
0421
0422 #define CVT_PXL_CLK_GRAN 250000
0423 #define CVT_PXL_CLK_GRAN_RB_V2 1000
0424
0425
0426 #define CVT_MIN_V_BPORCH 7
0427 #define CVT_MIN_V_PORCH_RND 3
0428 #define CVT_MIN_VSYNC_BP 550
0429 #define CVT_HSYNC_PERCENT 8
0430
0431
0432 #define CVT_CELL_GRAN 8
0433 #define CVT_M 600
0434 #define CVT_C 40
0435 #define CVT_K 128
0436 #define CVT_J 20
0437 #define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J)
0438 #define CVT_M_PRIME (CVT_K * CVT_M / 256)
0439
0440
0441 #define CVT_RB_MIN_V_BPORCH 7
0442 #define CVT_RB_V_FPORCH 3
0443 #define CVT_RB_MIN_V_BLANK 460
0444 #define CVT_RB_H_SYNC 32
0445 #define CVT_RB_H_BLANK 160
0446
0447 #define CVT_RB_V2_H_BLANK 80
0448 #define CVT_RB_MIN_V_FPORCH 3
0449 #define CVT_RB_V2_MIN_V_FPORCH 1
0450 #define CVT_RB_V_BPORCH 6
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468 bool v4l2_detect_cvt(unsigned frame_height,
0469 unsigned hfreq,
0470 unsigned vsync,
0471 unsigned active_width,
0472 u32 polarities,
0473 bool interlaced,
0474 struct v4l2_dv_timings *fmt)
0475 {
0476 int v_fp, v_bp, h_fp, h_bp, hsync;
0477 int frame_width, image_height, image_width;
0478 bool reduced_blanking;
0479 bool rb_v2 = false;
0480 unsigned pix_clk;
0481
0482 if (vsync < 4 || vsync > 8)
0483 return false;
0484
0485 if (polarities == V4L2_DV_VSYNC_POS_POL)
0486 reduced_blanking = false;
0487 else if (polarities == V4L2_DV_HSYNC_POS_POL)
0488 reduced_blanking = true;
0489 else
0490 return false;
0491
0492 if (reduced_blanking && vsync == 8)
0493 rb_v2 = true;
0494
0495 if (rb_v2 && active_width == 0)
0496 return false;
0497
0498 if (!rb_v2 && vsync > 7)
0499 return false;
0500
0501 if (hfreq == 0)
0502 return false;
0503
0504
0505 if (reduced_blanking) {
0506 if (rb_v2) {
0507 v_bp = CVT_RB_V_BPORCH;
0508 v_fp = (CVT_RB_MIN_V_BLANK * hfreq) / 1000000 + 1;
0509 v_fp -= vsync + v_bp;
0510
0511 if (v_fp < CVT_RB_V2_MIN_V_FPORCH)
0512 v_fp = CVT_RB_V2_MIN_V_FPORCH;
0513 } else {
0514 v_fp = CVT_RB_V_FPORCH;
0515 v_bp = (CVT_RB_MIN_V_BLANK * hfreq) / 1000000 + 1;
0516 v_bp -= vsync + v_fp;
0517
0518 if (v_bp < CVT_RB_MIN_V_BPORCH)
0519 v_bp = CVT_RB_MIN_V_BPORCH;
0520 }
0521 } else {
0522 v_fp = CVT_MIN_V_PORCH_RND;
0523 v_bp = (CVT_MIN_VSYNC_BP * hfreq) / 1000000 + 1 - vsync;
0524
0525 if (v_bp < CVT_MIN_V_BPORCH)
0526 v_bp = CVT_MIN_V_BPORCH;
0527 }
0528
0529 if (interlaced)
0530 image_height = (frame_height - 2 * v_fp - 2 * vsync - 2 * v_bp) & ~0x1;
0531 else
0532 image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
0533
0534 if (image_height < 0)
0535 return false;
0536
0537
0538 switch (vsync) {
0539 case 4:
0540 image_width = (image_height * 4) / 3;
0541 break;
0542 case 5:
0543 image_width = (image_height * 16) / 9;
0544 break;
0545 case 6:
0546 image_width = (image_height * 16) / 10;
0547 break;
0548 case 7:
0549
0550 if (image_height == 1024)
0551 image_width = (image_height * 5) / 4;
0552 else if (image_height == 768)
0553 image_width = (image_height * 15) / 9;
0554 else
0555 return false;
0556 break;
0557 case 8:
0558 image_width = active_width;
0559 break;
0560 default:
0561 return false;
0562 }
0563
0564 if (!rb_v2)
0565 image_width = image_width & ~7;
0566
0567
0568 if (reduced_blanking) {
0569 int h_blank;
0570 int clk_gran;
0571
0572 h_blank = rb_v2 ? CVT_RB_V2_H_BLANK : CVT_RB_H_BLANK;
0573 clk_gran = rb_v2 ? CVT_PXL_CLK_GRAN_RB_V2 : CVT_PXL_CLK_GRAN;
0574
0575 pix_clk = (image_width + h_blank) * hfreq;
0576 pix_clk = (pix_clk / clk_gran) * clk_gran;
0577
0578 h_bp = h_blank / 2;
0579 hsync = CVT_RB_H_SYNC;
0580 h_fp = h_blank - h_bp - hsync;
0581
0582 frame_width = image_width + h_blank;
0583 } else {
0584 unsigned ideal_duty_cycle_per_myriad =
0585 100 * CVT_C_PRIME - (CVT_M_PRIME * 100000) / hfreq;
0586 int h_blank;
0587
0588 if (ideal_duty_cycle_per_myriad < 2000)
0589 ideal_duty_cycle_per_myriad = 2000;
0590
0591 h_blank = image_width * ideal_duty_cycle_per_myriad /
0592 (10000 - ideal_duty_cycle_per_myriad);
0593 h_blank = (h_blank / (2 * CVT_CELL_GRAN)) * 2 * CVT_CELL_GRAN;
0594
0595 pix_clk = (image_width + h_blank) * hfreq;
0596 pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN;
0597
0598 h_bp = h_blank / 2;
0599 frame_width = image_width + h_blank;
0600
0601 hsync = frame_width * CVT_HSYNC_PERCENT / 100;
0602 hsync = (hsync / CVT_CELL_GRAN) * CVT_CELL_GRAN;
0603 h_fp = h_blank - hsync - h_bp;
0604 }
0605
0606 fmt->type = V4L2_DV_BT_656_1120;
0607 fmt->bt.polarities = polarities;
0608 fmt->bt.width = image_width;
0609 fmt->bt.height = image_height;
0610 fmt->bt.hfrontporch = h_fp;
0611 fmt->bt.vfrontporch = v_fp;
0612 fmt->bt.hsync = hsync;
0613 fmt->bt.vsync = vsync;
0614 fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
0615
0616 if (!interlaced) {
0617 fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
0618 fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
0619 } else {
0620 fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
0621 2 * vsync) / 2;
0622 fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
0623 2 * vsync - fmt->bt.vbackporch;
0624 fmt->bt.il_vfrontporch = v_fp;
0625 fmt->bt.il_vsync = vsync;
0626 fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
0627 fmt->bt.interlaced = V4L2_DV_INTERLACED;
0628 }
0629
0630 fmt->bt.pixelclock = pix_clk;
0631 fmt->bt.standards = V4L2_DV_BT_STD_CVT;
0632
0633 if (reduced_blanking)
0634 fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
0635
0636 return true;
0637 }
0638 EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
0639
0640
0641
0642
0643
0644
0645
0646 #define GTF_PXL_CLK_GRAN 250000
0647
0648 #define GTF_MIN_VSYNC_BP 550
0649 #define GTF_V_FP 1
0650 #define GTF_CELL_GRAN 8
0651
0652
0653 #define GTF_D_M 600
0654 #define GTF_D_C 40
0655 #define GTF_D_K 128
0656 #define GTF_D_J 20
0657 #define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J)
0658 #define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256)
0659
0660
0661 #define GTF_S_M 3600
0662 #define GTF_S_C 40
0663 #define GTF_S_K 128
0664 #define GTF_S_J 35
0665 #define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J)
0666 #define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256)
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686 bool v4l2_detect_gtf(unsigned frame_height,
0687 unsigned hfreq,
0688 unsigned vsync,
0689 u32 polarities,
0690 bool interlaced,
0691 struct v4l2_fract aspect,
0692 struct v4l2_dv_timings *fmt)
0693 {
0694 int pix_clk;
0695 int v_fp, v_bp, h_fp, hsync;
0696 int frame_width, image_height, image_width;
0697 bool default_gtf;
0698 int h_blank;
0699
0700 if (vsync != 3)
0701 return false;
0702
0703 if (polarities == V4L2_DV_VSYNC_POS_POL)
0704 default_gtf = true;
0705 else if (polarities == V4L2_DV_HSYNC_POS_POL)
0706 default_gtf = false;
0707 else
0708 return false;
0709
0710 if (hfreq == 0)
0711 return false;
0712
0713
0714 v_fp = GTF_V_FP;
0715 v_bp = (GTF_MIN_VSYNC_BP * hfreq + 500000) / 1000000 - vsync;
0716 if (interlaced)
0717 image_height = (frame_height - 2 * v_fp - 2 * vsync - 2 * v_bp) & ~0x1;
0718 else
0719 image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
0720
0721 if (image_height < 0)
0722 return false;
0723
0724 if (aspect.numerator == 0 || aspect.denominator == 0) {
0725 aspect.numerator = 16;
0726 aspect.denominator = 9;
0727 }
0728 image_width = ((image_height * aspect.numerator) / aspect.denominator);
0729 image_width = (image_width + GTF_CELL_GRAN/2) & ~(GTF_CELL_GRAN - 1);
0730
0731
0732 if (default_gtf) {
0733 u64 num;
0734 u32 den;
0735
0736 num = ((image_width * GTF_D_C_PRIME * (u64)hfreq) -
0737 ((u64)image_width * GTF_D_M_PRIME * 1000));
0738 den = (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) *
0739 (2 * GTF_CELL_GRAN);
0740 h_blank = div_u64((num + (den >> 1)), den);
0741 h_blank *= (2 * GTF_CELL_GRAN);
0742 } else {
0743 u64 num;
0744 u32 den;
0745
0746 num = ((image_width * GTF_S_C_PRIME * (u64)hfreq) -
0747 ((u64)image_width * GTF_S_M_PRIME * 1000));
0748 den = (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) *
0749 (2 * GTF_CELL_GRAN);
0750 h_blank = div_u64((num + (den >> 1)), den);
0751 h_blank *= (2 * GTF_CELL_GRAN);
0752 }
0753
0754 frame_width = image_width + h_blank;
0755
0756 pix_clk = (image_width + h_blank) * hfreq;
0757 pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN;
0758
0759 hsync = (frame_width * 8 + 50) / 100;
0760 hsync = DIV_ROUND_CLOSEST(hsync, GTF_CELL_GRAN) * GTF_CELL_GRAN;
0761
0762 h_fp = h_blank / 2 - hsync;
0763
0764 fmt->type = V4L2_DV_BT_656_1120;
0765 fmt->bt.polarities = polarities;
0766 fmt->bt.width = image_width;
0767 fmt->bt.height = image_height;
0768 fmt->bt.hfrontporch = h_fp;
0769 fmt->bt.vfrontporch = v_fp;
0770 fmt->bt.hsync = hsync;
0771 fmt->bt.vsync = vsync;
0772 fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
0773
0774 if (!interlaced) {
0775 fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
0776 fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
0777 } else {
0778 fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
0779 2 * vsync) / 2;
0780 fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
0781 2 * vsync - fmt->bt.vbackporch;
0782 fmt->bt.il_vfrontporch = v_fp;
0783 fmt->bt.il_vsync = vsync;
0784 fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
0785 fmt->bt.interlaced = V4L2_DV_INTERLACED;
0786 }
0787
0788 fmt->bt.pixelclock = pix_clk;
0789 fmt->bt.standards = V4L2_DV_BT_STD_GTF;
0790
0791 if (!default_gtf)
0792 fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
0793
0794 return true;
0795 }
0796 EXPORT_SYMBOL_GPL(v4l2_detect_gtf);
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807 struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait)
0808 {
0809 struct v4l2_fract aspect = { 16, 9 };
0810 u8 ratio;
0811
0812
0813 if (!hor_landscape && !vert_portrait)
0814 return aspect;
0815
0816 if (hor_landscape && vert_portrait) {
0817 aspect.numerator = hor_landscape;
0818 aspect.denominator = vert_portrait;
0819 return aspect;
0820 }
0821
0822
0823 ratio = hor_landscape | vert_portrait;
0824
0825 if (ratio == 79) {
0826 aspect.numerator = 16;
0827 aspect.denominator = 9;
0828 } else if (ratio == 34) {
0829 aspect.numerator = 4;
0830 aspect.denominator = 3;
0831 } else if (ratio == 68) {
0832 aspect.numerator = 15;
0833 aspect.denominator = 9;
0834 } else {
0835 aspect.numerator = hor_landscape + 99;
0836 aspect.denominator = 100;
0837 }
0838 if (hor_landscape)
0839 return aspect;
0840
0841 swap(aspect.denominator, aspect.numerator);
0842 return aspect;
0843 }
0844 EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio);
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859 struct v4l2_hdmi_colorimetry
0860 v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi,
0861 const struct hdmi_vendor_infoframe *hdmi,
0862 unsigned int height)
0863 {
0864 struct v4l2_hdmi_colorimetry c = {
0865 V4L2_COLORSPACE_SRGB,
0866 V4L2_YCBCR_ENC_DEFAULT,
0867 V4L2_QUANTIZATION_FULL_RANGE,
0868 V4L2_XFER_FUNC_SRGB
0869 };
0870 bool is_ce = avi->video_code || (hdmi && hdmi->vic);
0871 bool is_sdtv = height <= 576;
0872 bool default_is_lim_range_rgb = avi->video_code > 1;
0873
0874 switch (avi->colorspace) {
0875 case HDMI_COLORSPACE_RGB:
0876
0877 switch (avi->colorimetry) {
0878 case HDMI_COLORIMETRY_EXTENDED:
0879 switch (avi->extended_colorimetry) {
0880 case HDMI_EXTENDED_COLORIMETRY_OPRGB:
0881 c.colorspace = V4L2_COLORSPACE_OPRGB;
0882 c.xfer_func = V4L2_XFER_FUNC_OPRGB;
0883 break;
0884 case HDMI_EXTENDED_COLORIMETRY_BT2020:
0885 c.colorspace = V4L2_COLORSPACE_BT2020;
0886 c.xfer_func = V4L2_XFER_FUNC_709;
0887 break;
0888 default:
0889 break;
0890 }
0891 break;
0892 default:
0893 break;
0894 }
0895 switch (avi->quantization_range) {
0896 case HDMI_QUANTIZATION_RANGE_LIMITED:
0897 c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
0898 break;
0899 case HDMI_QUANTIZATION_RANGE_FULL:
0900 break;
0901 default:
0902 if (default_is_lim_range_rgb)
0903 c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
0904 break;
0905 }
0906 break;
0907
0908 default:
0909
0910 c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
0911 switch (avi->colorimetry) {
0912 case HDMI_COLORIMETRY_NONE:
0913 if (!is_ce)
0914 break;
0915 if (is_sdtv) {
0916 c.colorspace = V4L2_COLORSPACE_SMPTE170M;
0917 c.ycbcr_enc = V4L2_YCBCR_ENC_601;
0918 } else {
0919 c.colorspace = V4L2_COLORSPACE_REC709;
0920 c.ycbcr_enc = V4L2_YCBCR_ENC_709;
0921 }
0922 c.xfer_func = V4L2_XFER_FUNC_709;
0923 break;
0924 case HDMI_COLORIMETRY_ITU_601:
0925 c.colorspace = V4L2_COLORSPACE_SMPTE170M;
0926 c.ycbcr_enc = V4L2_YCBCR_ENC_601;
0927 c.xfer_func = V4L2_XFER_FUNC_709;
0928 break;
0929 case HDMI_COLORIMETRY_ITU_709:
0930 c.colorspace = V4L2_COLORSPACE_REC709;
0931 c.ycbcr_enc = V4L2_YCBCR_ENC_709;
0932 c.xfer_func = V4L2_XFER_FUNC_709;
0933 break;
0934 case HDMI_COLORIMETRY_EXTENDED:
0935 switch (avi->extended_colorimetry) {
0936 case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
0937 c.colorspace = V4L2_COLORSPACE_REC709;
0938 c.ycbcr_enc = V4L2_YCBCR_ENC_XV709;
0939 c.xfer_func = V4L2_XFER_FUNC_709;
0940 break;
0941 case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
0942 c.colorspace = V4L2_COLORSPACE_REC709;
0943 c.ycbcr_enc = V4L2_YCBCR_ENC_XV601;
0944 c.xfer_func = V4L2_XFER_FUNC_709;
0945 break;
0946 case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
0947 c.colorspace = V4L2_COLORSPACE_SRGB;
0948 c.ycbcr_enc = V4L2_YCBCR_ENC_601;
0949 c.xfer_func = V4L2_XFER_FUNC_SRGB;
0950 break;
0951 case HDMI_EXTENDED_COLORIMETRY_OPYCC_601:
0952 c.colorspace = V4L2_COLORSPACE_OPRGB;
0953 c.ycbcr_enc = V4L2_YCBCR_ENC_601;
0954 c.xfer_func = V4L2_XFER_FUNC_OPRGB;
0955 break;
0956 case HDMI_EXTENDED_COLORIMETRY_BT2020:
0957 c.colorspace = V4L2_COLORSPACE_BT2020;
0958 c.ycbcr_enc = V4L2_YCBCR_ENC_BT2020;
0959 c.xfer_func = V4L2_XFER_FUNC_709;
0960 break;
0961 case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
0962 c.colorspace = V4L2_COLORSPACE_BT2020;
0963 c.ycbcr_enc = V4L2_YCBCR_ENC_BT2020_CONST_LUM;
0964 c.xfer_func = V4L2_XFER_FUNC_709;
0965 break;
0966 default:
0967 c.colorspace = V4L2_COLORSPACE_REC709;
0968 c.ycbcr_enc = V4L2_YCBCR_ENC_709;
0969 c.xfer_func = V4L2_XFER_FUNC_709;
0970 break;
0971 }
0972 break;
0973 default:
0974 break;
0975 }
0976
0977
0978
0979
0980 break;
0981 }
0982 return c;
0983 }
0984 EXPORT_SYMBOL_GPL(v4l2_hdmi_rx_colorimetry);
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997 u16 v4l2_get_edid_phys_addr(const u8 *edid, unsigned int size,
0998 unsigned int *offset)
0999 {
1000 unsigned int loc = cec_get_edid_spa_location(edid, size);
1001
1002 if (offset)
1003 *offset = loc;
1004 if (loc == 0)
1005 return CEC_PHYS_ADDR_INVALID;
1006 return (edid[loc] << 8) | edid[loc + 1];
1007 }
1008 EXPORT_SYMBOL_GPL(v4l2_get_edid_phys_addr);
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022 void v4l2_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr)
1023 {
1024 unsigned int loc = cec_get_edid_spa_location(edid, size);
1025 u8 sum = 0;
1026 unsigned int i;
1027
1028 if (loc == 0)
1029 return;
1030 edid[loc] = phys_addr >> 8;
1031 edid[loc + 1] = phys_addr & 0xff;
1032 loc &= ~0x7f;
1033
1034
1035 for (i = loc; i < loc + 127; i++)
1036 sum += edid[i];
1037 edid[i] = 256 - sum;
1038 }
1039 EXPORT_SYMBOL_GPL(v4l2_set_edid_phys_addr);
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060 u16 v4l2_phys_addr_for_input(u16 phys_addr, u8 input)
1061 {
1062
1063 if (WARN_ON(input == 0 || input > 0xf))
1064 return CEC_PHYS_ADDR_INVALID;
1065
1066 if (phys_addr == 0)
1067 return input << 12;
1068
1069 if ((phys_addr & 0x0fff) == 0)
1070 return phys_addr | (input << 8);
1071
1072 if ((phys_addr & 0x00ff) == 0)
1073 return phys_addr | (input << 4);
1074
1075 if ((phys_addr & 0x000f) == 0)
1076 return phys_addr | input;
1077
1078
1079
1080
1081
1082 return CEC_PHYS_ADDR_INVALID;
1083 }
1084 EXPORT_SYMBOL_GPL(v4l2_phys_addr_for_input);
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110 int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
1111 {
1112 int i;
1113
1114 if (parent)
1115 *parent = phys_addr;
1116 if (port)
1117 *port = 0;
1118 if (phys_addr == CEC_PHYS_ADDR_INVALID)
1119 return 0;
1120 for (i = 0; i < 16; i += 4)
1121 if (phys_addr & (0xf << i))
1122 break;
1123 if (i == 16)
1124 return 0;
1125 if (parent)
1126 *parent = phys_addr & (0xfff0 << i);
1127 if (port)
1128 *port = (phys_addr >> i) & 0xf;
1129 for (i += 4; i < 16; i += 4)
1130 if ((phys_addr & (0xf << i)) == 0)
1131 return -EINVAL;
1132 return 0;
1133 }
1134 EXPORT_SYMBOL_GPL(v4l2_phys_addr_validate);