0001
0002
0003
0004
0005
0006
0007
0008 #ifndef _V4L2_TPG_H_
0009 #define _V4L2_TPG_H_
0010
0011 #include <linux/types.h>
0012 #include <linux/errno.h>
0013 #include <linux/random.h>
0014 #include <linux/slab.h>
0015 #include <linux/vmalloc.h>
0016 #include <linux/videodev2.h>
0017
0018 struct tpg_rbg_color8 {
0019 unsigned char r, g, b;
0020 };
0021
0022 struct tpg_rbg_color16 {
0023 __u16 r, g, b;
0024 };
0025
0026 enum tpg_color {
0027 TPG_COLOR_CSC_WHITE,
0028 TPG_COLOR_CSC_YELLOW,
0029 TPG_COLOR_CSC_CYAN,
0030 TPG_COLOR_CSC_GREEN,
0031 TPG_COLOR_CSC_MAGENTA,
0032 TPG_COLOR_CSC_RED,
0033 TPG_COLOR_CSC_BLUE,
0034 TPG_COLOR_CSC_BLACK,
0035 TPG_COLOR_75_YELLOW,
0036 TPG_COLOR_75_CYAN,
0037 TPG_COLOR_75_GREEN,
0038 TPG_COLOR_75_MAGENTA,
0039 TPG_COLOR_75_RED,
0040 TPG_COLOR_75_BLUE,
0041 TPG_COLOR_100_WHITE,
0042 TPG_COLOR_100_YELLOW,
0043 TPG_COLOR_100_CYAN,
0044 TPG_COLOR_100_GREEN,
0045 TPG_COLOR_100_MAGENTA,
0046 TPG_COLOR_100_RED,
0047 TPG_COLOR_100_BLUE,
0048 TPG_COLOR_100_BLACK,
0049 TPG_COLOR_TEXTFG,
0050 TPG_COLOR_TEXTBG,
0051 TPG_COLOR_RANDOM,
0052 TPG_COLOR_RAMP,
0053 TPG_COLOR_MAX = TPG_COLOR_RAMP + 256
0054 };
0055
0056 extern const struct tpg_rbg_color8 tpg_colors[TPG_COLOR_MAX];
0057 extern const unsigned short tpg_rec709_to_linear[255 * 16 + 1];
0058 extern const unsigned short tpg_linear_to_rec709[255 * 16 + 1];
0059 extern const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1]
0060 [V4L2_XFER_FUNC_SMPTE2084 + 1]
0061 [TPG_COLOR_CSC_BLACK + 1];
0062 enum tpg_pattern {
0063 TPG_PAT_75_COLORBAR,
0064 TPG_PAT_100_COLORBAR,
0065 TPG_PAT_CSC_COLORBAR,
0066 TPG_PAT_100_HCOLORBAR,
0067 TPG_PAT_100_COLORSQUARES,
0068 TPG_PAT_BLACK,
0069 TPG_PAT_WHITE,
0070 TPG_PAT_RED,
0071 TPG_PAT_GREEN,
0072 TPG_PAT_BLUE,
0073 TPG_PAT_CHECKERS_16X16,
0074 TPG_PAT_CHECKERS_2X2,
0075 TPG_PAT_CHECKERS_1X1,
0076 TPG_PAT_COLOR_CHECKERS_2X2,
0077 TPG_PAT_COLOR_CHECKERS_1X1,
0078 TPG_PAT_ALTERNATING_HLINES,
0079 TPG_PAT_ALTERNATING_VLINES,
0080 TPG_PAT_CROSS_1_PIXEL,
0081 TPG_PAT_CROSS_2_PIXELS,
0082 TPG_PAT_CROSS_10_PIXELS,
0083 TPG_PAT_GRAY_RAMP,
0084
0085
0086 TPG_PAT_NOISE,
0087 };
0088
0089 extern const char * const tpg_pattern_strings[];
0090
0091 enum tpg_quality {
0092 TPG_QUAL_COLOR,
0093 TPG_QUAL_GRAY,
0094 TPG_QUAL_NOISE
0095 };
0096
0097 enum tpg_video_aspect {
0098 TPG_VIDEO_ASPECT_IMAGE,
0099 TPG_VIDEO_ASPECT_4X3,
0100 TPG_VIDEO_ASPECT_14X9_CENTRE,
0101 TPG_VIDEO_ASPECT_16X9_CENTRE,
0102 TPG_VIDEO_ASPECT_16X9_ANAMORPHIC,
0103 };
0104
0105 enum tpg_pixel_aspect {
0106 TPG_PIXEL_ASPECT_SQUARE,
0107 TPG_PIXEL_ASPECT_NTSC,
0108 TPG_PIXEL_ASPECT_PAL,
0109 };
0110
0111 enum tpg_move_mode {
0112 TPG_MOVE_NEG_FAST,
0113 TPG_MOVE_NEG,
0114 TPG_MOVE_NEG_SLOW,
0115 TPG_MOVE_NONE,
0116 TPG_MOVE_POS_SLOW,
0117 TPG_MOVE_POS,
0118 TPG_MOVE_POS_FAST,
0119 };
0120
0121 enum tgp_color_enc {
0122 TGP_COLOR_ENC_RGB,
0123 TGP_COLOR_ENC_YCBCR,
0124 TGP_COLOR_ENC_HSV,
0125 TGP_COLOR_ENC_LUMA,
0126 };
0127
0128 extern const char * const tpg_aspect_strings[];
0129
0130 #define TPG_MAX_PLANES 3
0131 #define TPG_MAX_PAT_LINES 8
0132
0133 struct tpg_data {
0134
0135 unsigned src_width, src_height;
0136
0137 unsigned buf_height;
0138
0139 unsigned scaled_width;
0140 u32 field;
0141 bool field_alternate;
0142
0143 struct v4l2_rect crop;
0144
0145 struct v4l2_rect compose;
0146
0147 struct v4l2_rect border;
0148 struct v4l2_rect square;
0149
0150
0151 enum tpg_quality qual;
0152 unsigned qual_offset;
0153 u8 alpha_component;
0154 bool alpha_red_only;
0155 u8 brightness;
0156 u8 contrast;
0157 u8 saturation;
0158 s16 hue;
0159 u32 fourcc;
0160 enum tgp_color_enc color_enc;
0161 u32 colorspace;
0162 u32 xfer_func;
0163 u32 ycbcr_enc;
0164 u32 hsv_enc;
0165
0166
0167
0168
0169 u32 real_xfer_func;
0170
0171
0172
0173
0174 u32 real_hsv_enc;
0175 u32 real_ycbcr_enc;
0176 u32 quantization;
0177
0178
0179
0180
0181 u32 real_quantization;
0182 enum tpg_video_aspect vid_aspect;
0183 enum tpg_pixel_aspect pix_aspect;
0184 unsigned rgb_range;
0185 unsigned real_rgb_range;
0186 unsigned buffers;
0187 unsigned planes;
0188 bool interleaved;
0189 u8 vdownsampling[TPG_MAX_PLANES];
0190 u8 hdownsampling[TPG_MAX_PLANES];
0191
0192
0193
0194
0195 unsigned hmask[TPG_MAX_PLANES];
0196
0197 u8 colors[TPG_COLOR_MAX][3];
0198 u8 textfg[TPG_MAX_PLANES][8], textbg[TPG_MAX_PLANES][8];
0199
0200 unsigned twopixelsize[TPG_MAX_PLANES];
0201 unsigned bytesperline[TPG_MAX_PLANES];
0202
0203
0204 enum tpg_pattern pattern;
0205 bool hflip;
0206 bool vflip;
0207 unsigned perc_fill;
0208 bool perc_fill_blank;
0209 bool show_border;
0210 bool show_square;
0211 bool insert_sav;
0212 bool insert_eav;
0213 bool insert_hdmi_video_guard_band;
0214
0215
0216 enum tpg_move_mode mv_hor_mode;
0217 int mv_hor_count;
0218 int mv_hor_step;
0219 enum tpg_move_mode mv_vert_mode;
0220 int mv_vert_count;
0221 int mv_vert_step;
0222
0223 bool recalc_colors;
0224 bool recalc_lines;
0225 bool recalc_square_border;
0226
0227
0228 unsigned max_line_width;
0229 u8 *lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES];
0230 u8 *downsampled_lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES];
0231 u8 *random_line[TPG_MAX_PLANES];
0232 u8 *contrast_line[TPG_MAX_PLANES];
0233 u8 *black_line[TPG_MAX_PLANES];
0234 };
0235
0236 void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h);
0237 int tpg_alloc(struct tpg_data *tpg, unsigned max_w);
0238 void tpg_free(struct tpg_data *tpg);
0239 void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
0240 u32 field);
0241 void tpg_log_status(struct tpg_data *tpg);
0242
0243 void tpg_set_font(const u8 *f);
0244 void tpg_gen_text(const struct tpg_data *tpg,
0245 u8 *basep[TPG_MAX_PLANES][2], int y, int x, const char *text);
0246 void tpg_calc_text_basep(struct tpg_data *tpg,
0247 u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf);
0248 unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line);
0249 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
0250 unsigned p, u8 *vbuf);
0251 void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std,
0252 unsigned p, u8 *vbuf);
0253 bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc);
0254 void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop,
0255 const struct v4l2_rect *compose);
0256 const char *tpg_g_color_order(const struct tpg_data *tpg);
0257
0258 static inline void tpg_s_pattern(struct tpg_data *tpg, enum tpg_pattern pattern)
0259 {
0260 if (tpg->pattern == pattern)
0261 return;
0262 tpg->pattern = pattern;
0263 tpg->recalc_colors = true;
0264 }
0265
0266 static inline void tpg_s_quality(struct tpg_data *tpg,
0267 enum tpg_quality qual, unsigned qual_offset)
0268 {
0269 if (tpg->qual == qual && tpg->qual_offset == qual_offset)
0270 return;
0271 tpg->qual = qual;
0272 tpg->qual_offset = qual_offset;
0273 tpg->recalc_colors = true;
0274 }
0275
0276 static inline enum tpg_quality tpg_g_quality(const struct tpg_data *tpg)
0277 {
0278 return tpg->qual;
0279 }
0280
0281 static inline void tpg_s_alpha_component(struct tpg_data *tpg,
0282 u8 alpha_component)
0283 {
0284 if (tpg->alpha_component == alpha_component)
0285 return;
0286 tpg->alpha_component = alpha_component;
0287 tpg->recalc_colors = true;
0288 }
0289
0290 static inline void tpg_s_alpha_mode(struct tpg_data *tpg,
0291 bool red_only)
0292 {
0293 if (tpg->alpha_red_only == red_only)
0294 return;
0295 tpg->alpha_red_only = red_only;
0296 tpg->recalc_colors = true;
0297 }
0298
0299 static inline void tpg_s_brightness(struct tpg_data *tpg,
0300 u8 brightness)
0301 {
0302 if (tpg->brightness == brightness)
0303 return;
0304 tpg->brightness = brightness;
0305 tpg->recalc_colors = true;
0306 }
0307
0308 static inline void tpg_s_contrast(struct tpg_data *tpg,
0309 u8 contrast)
0310 {
0311 if (tpg->contrast == contrast)
0312 return;
0313 tpg->contrast = contrast;
0314 tpg->recalc_colors = true;
0315 }
0316
0317 static inline void tpg_s_saturation(struct tpg_data *tpg,
0318 u8 saturation)
0319 {
0320 if (tpg->saturation == saturation)
0321 return;
0322 tpg->saturation = saturation;
0323 tpg->recalc_colors = true;
0324 }
0325
0326 static inline void tpg_s_hue(struct tpg_data *tpg,
0327 s16 hue)
0328 {
0329 hue = clamp_t(s16, hue, -128, 128);
0330 if (tpg->hue == hue)
0331 return;
0332 tpg->hue = hue;
0333 tpg->recalc_colors = true;
0334 }
0335
0336 static inline void tpg_s_rgb_range(struct tpg_data *tpg,
0337 unsigned rgb_range)
0338 {
0339 if (tpg->rgb_range == rgb_range)
0340 return;
0341 tpg->rgb_range = rgb_range;
0342 tpg->recalc_colors = true;
0343 }
0344
0345 static inline void tpg_s_real_rgb_range(struct tpg_data *tpg,
0346 unsigned rgb_range)
0347 {
0348 if (tpg->real_rgb_range == rgb_range)
0349 return;
0350 tpg->real_rgb_range = rgb_range;
0351 tpg->recalc_colors = true;
0352 }
0353
0354 static inline void tpg_s_colorspace(struct tpg_data *tpg, u32 colorspace)
0355 {
0356 if (tpg->colorspace == colorspace)
0357 return;
0358 tpg->colorspace = colorspace;
0359 tpg->recalc_colors = true;
0360 }
0361
0362 static inline u32 tpg_g_colorspace(const struct tpg_data *tpg)
0363 {
0364 return tpg->colorspace;
0365 }
0366
0367 static inline void tpg_s_ycbcr_enc(struct tpg_data *tpg, u32 ycbcr_enc)
0368 {
0369 if (tpg->ycbcr_enc == ycbcr_enc)
0370 return;
0371 tpg->ycbcr_enc = ycbcr_enc;
0372 tpg->recalc_colors = true;
0373 }
0374
0375 static inline u32 tpg_g_ycbcr_enc(const struct tpg_data *tpg)
0376 {
0377 return tpg->ycbcr_enc;
0378 }
0379
0380 static inline void tpg_s_hsv_enc(struct tpg_data *tpg, u32 hsv_enc)
0381 {
0382 if (tpg->hsv_enc == hsv_enc)
0383 return;
0384 tpg->hsv_enc = hsv_enc;
0385 tpg->recalc_colors = true;
0386 }
0387
0388 static inline u32 tpg_g_hsv_enc(const struct tpg_data *tpg)
0389 {
0390 return tpg->hsv_enc;
0391 }
0392
0393 static inline void tpg_s_xfer_func(struct tpg_data *tpg, u32 xfer_func)
0394 {
0395 if (tpg->xfer_func == xfer_func)
0396 return;
0397 tpg->xfer_func = xfer_func;
0398 tpg->recalc_colors = true;
0399 }
0400
0401 static inline u32 tpg_g_xfer_func(const struct tpg_data *tpg)
0402 {
0403 return tpg->xfer_func;
0404 }
0405
0406 static inline void tpg_s_quantization(struct tpg_data *tpg, u32 quantization)
0407 {
0408 if (tpg->quantization == quantization)
0409 return;
0410 tpg->quantization = quantization;
0411 tpg->recalc_colors = true;
0412 }
0413
0414 static inline u32 tpg_g_quantization(const struct tpg_data *tpg)
0415 {
0416 return tpg->quantization;
0417 }
0418
0419 static inline unsigned tpg_g_buffers(const struct tpg_data *tpg)
0420 {
0421 return tpg->buffers;
0422 }
0423
0424 static inline unsigned tpg_g_planes(const struct tpg_data *tpg)
0425 {
0426 return tpg->interleaved ? 1 : tpg->planes;
0427 }
0428
0429 static inline bool tpg_g_interleaved(const struct tpg_data *tpg)
0430 {
0431 return tpg->interleaved;
0432 }
0433
0434 static inline unsigned tpg_g_twopixelsize(const struct tpg_data *tpg, unsigned plane)
0435 {
0436 return tpg->twopixelsize[plane];
0437 }
0438
0439 static inline unsigned tpg_hdiv(const struct tpg_data *tpg,
0440 unsigned plane, unsigned x)
0441 {
0442 return ((x / tpg->hdownsampling[plane]) & tpg->hmask[plane]) *
0443 tpg->twopixelsize[plane] / 2;
0444 }
0445
0446 static inline unsigned tpg_hscale(const struct tpg_data *tpg, unsigned x)
0447 {
0448 return (x * tpg->scaled_width) / tpg->src_width;
0449 }
0450
0451 static inline unsigned tpg_hscale_div(const struct tpg_data *tpg,
0452 unsigned plane, unsigned x)
0453 {
0454 return tpg_hdiv(tpg, plane, tpg_hscale(tpg, x));
0455 }
0456
0457 static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned plane)
0458 {
0459 return tpg->bytesperline[plane];
0460 }
0461
0462 static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsigned bpl)
0463 {
0464 unsigned p;
0465
0466 if (tpg->buffers > 1) {
0467 tpg->bytesperline[plane] = bpl;
0468 return;
0469 }
0470
0471 for (p = 0; p < tpg_g_planes(tpg); p++) {
0472 unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
0473
0474 tpg->bytesperline[p] = plane_w / tpg->hdownsampling[p];
0475 }
0476 if (tpg_g_interleaved(tpg))
0477 tpg->bytesperline[1] = tpg->bytesperline[0];
0478 }
0479
0480
0481 static inline unsigned tpg_g_line_width(const struct tpg_data *tpg, unsigned plane)
0482 {
0483 unsigned w = 0;
0484 unsigned p;
0485
0486 if (tpg->buffers > 1)
0487 return tpg_g_bytesperline(tpg, plane);
0488 for (p = 0; p < tpg_g_planes(tpg); p++) {
0489 unsigned plane_w = tpg_g_bytesperline(tpg, p);
0490
0491 w += plane_w / tpg->vdownsampling[p];
0492 }
0493 return w;
0494 }
0495
0496 static inline unsigned tpg_calc_line_width(const struct tpg_data *tpg,
0497 unsigned plane, unsigned bpl)
0498 {
0499 unsigned w = 0;
0500 unsigned p;
0501
0502 if (tpg->buffers > 1)
0503 return bpl;
0504 for (p = 0; p < tpg_g_planes(tpg); p++) {
0505 unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
0506
0507 plane_w /= tpg->hdownsampling[p];
0508 w += plane_w / tpg->vdownsampling[p];
0509 }
0510 return w;
0511 }
0512
0513 static inline unsigned tpg_calc_plane_size(const struct tpg_data *tpg, unsigned plane)
0514 {
0515 if (plane >= tpg_g_planes(tpg))
0516 return 0;
0517
0518 return tpg_g_bytesperline(tpg, plane) * tpg->buf_height /
0519 tpg->vdownsampling[plane];
0520 }
0521
0522 static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h)
0523 {
0524 tpg->buf_height = h;
0525 }
0526
0527 static inline void tpg_s_field(struct tpg_data *tpg, unsigned field, bool alternate)
0528 {
0529 tpg->field = field;
0530 tpg->field_alternate = alternate;
0531 }
0532
0533 static inline void tpg_s_perc_fill(struct tpg_data *tpg,
0534 unsigned perc_fill)
0535 {
0536 tpg->perc_fill = perc_fill;
0537 }
0538
0539 static inline unsigned tpg_g_perc_fill(const struct tpg_data *tpg)
0540 {
0541 return tpg->perc_fill;
0542 }
0543
0544 static inline void tpg_s_perc_fill_blank(struct tpg_data *tpg,
0545 bool perc_fill_blank)
0546 {
0547 tpg->perc_fill_blank = perc_fill_blank;
0548 }
0549
0550 static inline void tpg_s_video_aspect(struct tpg_data *tpg,
0551 enum tpg_video_aspect vid_aspect)
0552 {
0553 if (tpg->vid_aspect == vid_aspect)
0554 return;
0555 tpg->vid_aspect = vid_aspect;
0556 tpg->recalc_square_border = true;
0557 }
0558
0559 static inline enum tpg_video_aspect tpg_g_video_aspect(const struct tpg_data *tpg)
0560 {
0561 return tpg->vid_aspect;
0562 }
0563
0564 static inline void tpg_s_pixel_aspect(struct tpg_data *tpg,
0565 enum tpg_pixel_aspect pix_aspect)
0566 {
0567 if (tpg->pix_aspect == pix_aspect)
0568 return;
0569 tpg->pix_aspect = pix_aspect;
0570 tpg->recalc_square_border = true;
0571 }
0572
0573 static inline void tpg_s_show_border(struct tpg_data *tpg,
0574 bool show_border)
0575 {
0576 tpg->show_border = show_border;
0577 }
0578
0579 static inline void tpg_s_show_square(struct tpg_data *tpg,
0580 bool show_square)
0581 {
0582 tpg->show_square = show_square;
0583 }
0584
0585 static inline void tpg_s_insert_sav(struct tpg_data *tpg, bool insert_sav)
0586 {
0587 tpg->insert_sav = insert_sav;
0588 }
0589
0590 static inline void tpg_s_insert_eav(struct tpg_data *tpg, bool insert_eav)
0591 {
0592 tpg->insert_eav = insert_eav;
0593 }
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604 static inline void tpg_s_insert_hdmi_video_guard_band(struct tpg_data *tpg,
0605 bool insert_hdmi_video_guard_band)
0606 {
0607 tpg->insert_hdmi_video_guard_band = insert_hdmi_video_guard_band;
0608 }
0609
0610 void tpg_update_mv_step(struct tpg_data *tpg);
0611
0612 static inline void tpg_s_mv_hor_mode(struct tpg_data *tpg,
0613 enum tpg_move_mode mv_hor_mode)
0614 {
0615 tpg->mv_hor_mode = mv_hor_mode;
0616 tpg_update_mv_step(tpg);
0617 }
0618
0619 static inline void tpg_s_mv_vert_mode(struct tpg_data *tpg,
0620 enum tpg_move_mode mv_vert_mode)
0621 {
0622 tpg->mv_vert_mode = mv_vert_mode;
0623 tpg_update_mv_step(tpg);
0624 }
0625
0626 static inline void tpg_init_mv_count(struct tpg_data *tpg)
0627 {
0628 tpg->mv_hor_count = tpg->mv_vert_count = 0;
0629 }
0630
0631 static inline void tpg_update_mv_count(struct tpg_data *tpg, bool frame_is_field)
0632 {
0633 tpg->mv_hor_count += tpg->mv_hor_step * (frame_is_field ? 1 : 2);
0634 tpg->mv_vert_count += tpg->mv_vert_step * (frame_is_field ? 1 : 2);
0635 }
0636
0637 static inline void tpg_s_hflip(struct tpg_data *tpg, bool hflip)
0638 {
0639 if (tpg->hflip == hflip)
0640 return;
0641 tpg->hflip = hflip;
0642 tpg_update_mv_step(tpg);
0643 tpg->recalc_lines = true;
0644 }
0645
0646 static inline bool tpg_g_hflip(const struct tpg_data *tpg)
0647 {
0648 return tpg->hflip;
0649 }
0650
0651 static inline void tpg_s_vflip(struct tpg_data *tpg, bool vflip)
0652 {
0653 tpg->vflip = vflip;
0654 }
0655
0656 static inline bool tpg_g_vflip(const struct tpg_data *tpg)
0657 {
0658 return tpg->vflip;
0659 }
0660
0661 static inline bool tpg_pattern_is_static(const struct tpg_data *tpg)
0662 {
0663 return tpg->pattern != TPG_PAT_NOISE &&
0664 tpg->mv_hor_mode == TPG_MOVE_NONE &&
0665 tpg->mv_vert_mode == TPG_MOVE_NONE;
0666 }
0667
0668 #endif