diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-01-11 08:29:43 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:42:20 -0400 |
commit | e164b58a84cc9fdff0653dfe38470c0216df31d2 (patch) | |
tree | 21c11370d328b3dc43cc1503ea1562c46db032a3 /drivers/media/video/vivi.c | |
parent | 0d34fb8e93ceba7b6dad0062dbb4a0813bacd75b (diff) |
V4L/DVB (10211): vivi: Implements 4 inputs on vivi
This patch adds the capability of selecting between 4 different inputs
on vivi driver. Input 0 is the normal color bar, while inputs 1-3 are
modified color bars.
This allows testing input selection on userspace applications and
serves as an implementation model for other drivers.
The current approach allows a maximum of 10 different inputs, since the
input name generator assumes that we need just one digit to present the
input. It shouldn't be hard to modify it to present a bigger name of
inputs, but, in fact, it doesn't make much sense of doing it for this
test driver.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/vivi.c')
-rw-r--r-- | drivers/media/video/vivi.c | 186 |
1 files changed, 142 insertions, 44 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 81d5aa5cf331..13e7bd06a80c 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -223,6 +223,9 @@ struct vivi_dev { | |||
223 | char timestr[13]; | 223 | char timestr[13]; |
224 | 224 | ||
225 | int mv_count; /* Controls bars movement */ | 225 | int mv_count; /* Controls bars movement */ |
226 | |||
227 | /* Input Number */ | ||
228 | int input; | ||
226 | }; | 229 | }; |
227 | 230 | ||
228 | struct vivi_fh { | 231 | struct vivi_fh { |
@@ -235,6 +238,7 @@ struct vivi_fh { | |||
235 | 238 | ||
236 | enum v4l2_buf_type type; | 239 | enum v4l2_buf_type type; |
237 | unsigned char bars[8][3]; | 240 | unsigned char bars[8][3]; |
241 | int input; /* Input Number on bars */ | ||
238 | }; | 242 | }; |
239 | 243 | ||
240 | /* ------------------------------------------------------------------ | 244 | /* ------------------------------------------------------------------ |
@@ -254,18 +258,72 @@ enum colors { | |||
254 | BLACK, | 258 | BLACK, |
255 | }; | 259 | }; |
256 | 260 | ||
257 | static u8 bars[8][3] = { | ||
258 | /* R G B */ | 261 | /* R G B */ |
259 | {204, 204, 204}, /* white */ | 262 | #define COLOR_WHITE {204, 204, 204} |
260 | {208, 208, 0}, /* ambar */ | 263 | #define COLOR_AMBAR {208, 208, 0} |
261 | { 0, 206, 206}, /* cyan */ | 264 | #define COLOR_CIAN { 0, 206, 206} |
262 | { 0, 239, 0}, /* green */ | 265 | #define COLOR_GREEN { 0, 239, 0} |
263 | {239, 0, 239}, /* magenta */ | 266 | #define COLOR_MAGENTA {239, 0, 239} |
264 | {205, 0, 0}, /* red */ | 267 | #define COLOR_RED {205, 0, 0} |
265 | { 0, 0, 255}, /* blue */ | 268 | #define COLOR_BLUE { 0, 0, 255} |
266 | { 0, 0, 0}, /* black */ | 269 | #define COLOR_BLACK { 0, 0, 0} |
270 | |||
271 | struct bar_std { | ||
272 | u8 bar[8][3]; | ||
273 | }; | ||
274 | |||
275 | /* Maximum number of bars are 10 - otherwise, the input print code | ||
276 | should be modified */ | ||
277 | static struct bar_std bars[] = { | ||
278 | { /* Standard ITU-R color bar sequence */ | ||
279 | { | ||
280 | COLOR_WHITE, | ||
281 | COLOR_AMBAR, | ||
282 | COLOR_CIAN, | ||
283 | COLOR_GREEN, | ||
284 | COLOR_MAGENTA, | ||
285 | COLOR_RED, | ||
286 | COLOR_BLUE, | ||
287 | COLOR_BLACK, | ||
288 | } | ||
289 | }, { | ||
290 | { | ||
291 | COLOR_WHITE, | ||
292 | COLOR_AMBAR, | ||
293 | COLOR_BLACK, | ||
294 | COLOR_WHITE, | ||
295 | COLOR_AMBAR, | ||
296 | COLOR_BLACK, | ||
297 | COLOR_WHITE, | ||
298 | COLOR_AMBAR, | ||
299 | } | ||
300 | }, { | ||
301 | { | ||
302 | COLOR_WHITE, | ||
303 | COLOR_CIAN, | ||
304 | COLOR_BLACK, | ||
305 | COLOR_WHITE, | ||
306 | COLOR_CIAN, | ||
307 | COLOR_BLACK, | ||
308 | COLOR_WHITE, | ||
309 | COLOR_CIAN, | ||
310 | } | ||
311 | }, { | ||
312 | { | ||
313 | COLOR_WHITE, | ||
314 | COLOR_GREEN, | ||
315 | COLOR_BLACK, | ||
316 | COLOR_WHITE, | ||
317 | COLOR_GREEN, | ||
318 | COLOR_BLACK, | ||
319 | COLOR_WHITE, | ||
320 | COLOR_GREEN, | ||
321 | } | ||
322 | }, | ||
267 | }; | 323 | }; |
268 | 324 | ||
325 | #define NUM_INPUTS ARRAY_SIZE(bars) | ||
326 | |||
269 | #define TO_Y(r, g, b) \ | 327 | #define TO_Y(r, g, b) \ |
270 | (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16) | 328 | (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16) |
271 | /* RGB to V(Cr) Color transform */ | 329 | /* RGB to V(Cr) Color transform */ |
@@ -275,9 +333,10 @@ static u8 bars[8][3] = { | |||
275 | #define TO_U(r, g, b) \ | 333 | #define TO_U(r, g, b) \ |
276 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) | 334 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) |
277 | 335 | ||
278 | #define TSTAMP_MIN_Y 24 | 336 | #define TSTAMP_MIN_Y 24 |
279 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 | 337 | #define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) |
280 | #define TSTAMP_MIN_X 64 | 338 | #define TSTAMP_INPUT_X 10 |
339 | #define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) | ||
281 | 340 | ||
282 | static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) | 341 | static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) |
283 | { | 342 | { |
@@ -392,9 +451,29 @@ static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax, | |||
392 | pos += 4; /* only 16 bpp supported for now */ | 451 | pos += 4; /* only 16 bpp supported for now */ |
393 | } | 452 | } |
394 | 453 | ||
395 | /* Checks if it is possible to show timestamp */ | 454 | /* Prints input entry number */ |
455 | |||
456 | /* Checks if it is possible to input number */ | ||
396 | if (TSTAMP_MAX_Y >= hmax) | 457 | if (TSTAMP_MAX_Y >= hmax) |
397 | goto end; | 458 | goto end; |
459 | |||
460 | if (TSTAMP_INPUT_X + strlen(timestr) >= wmax) | ||
461 | goto end; | ||
462 | |||
463 | if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) { | ||
464 | chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y]; | ||
465 | pos = TSTAMP_INPUT_X; | ||
466 | for (i = 0; i < 7; i++) { | ||
467 | /* Draw white font on black background */ | ||
468 | if (chr & 1 << (7 - i)) | ||
469 | gen_twopix(fh, basep + pos, WHITE); | ||
470 | else | ||
471 | gen_twopix(fh, basep + pos, BLACK); | ||
472 | pos += 2; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | /* Checks if it is possible to show timestamp */ | ||
398 | if (TSTAMP_MIN_X + strlen(timestr) >= wmax) | 477 | if (TSTAMP_MIN_X + strlen(timestr) >= wmax) |
399 | goto end; | 478 | goto end; |
400 | 479 | ||
@@ -807,38 +886,19 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
807 | return 0; | 886 | return 0; |
808 | } | 887 | } |
809 | 888 | ||
810 | /*FIXME: This seems to be generic enough to be at videodev2 */ | 889 | /* precalculate color bar values to speed up rendering */ |
811 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 890 | static void precalculate_bars(struct vivi_fh *fh) |
812 | struct v4l2_format *f) | ||
813 | { | 891 | { |
814 | struct vivi_fh *fh = priv; | 892 | struct vivi_dev *dev = fh->dev; |
815 | struct videobuf_queue *q = &fh->vb_vidq; | ||
816 | unsigned char r, g, b; | 893 | unsigned char r, g, b; |
817 | int k, is_yuv; | 894 | int k, is_yuv; |
818 | 895 | ||
819 | int ret = vidioc_try_fmt_vid_cap(file, fh, f); | 896 | fh->input = dev->input; |
820 | if (ret < 0) | ||
821 | return (ret); | ||
822 | |||
823 | mutex_lock(&q->vb_lock); | ||
824 | |||
825 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | ||
826 | dprintk(fh->dev, 1, "%s queue busy\n", __func__); | ||
827 | ret = -EBUSY; | ||
828 | goto out; | ||
829 | } | ||
830 | 897 | ||
831 | fh->fmt = get_format(f); | ||
832 | fh->width = f->fmt.pix.width; | ||
833 | fh->height = f->fmt.pix.height; | ||
834 | fh->vb_vidq.field = f->fmt.pix.field; | ||
835 | fh->type = f->type; | ||
836 | |||
837 | /* precalculate color bar values to speed up rendering */ | ||
838 | for (k = 0; k < 8; k++) { | 898 | for (k = 0; k < 8; k++) { |
839 | r = bars[k][0]; | 899 | r = bars[fh->input].bar[k][0]; |
840 | g = bars[k][1]; | 900 | g = bars[fh->input].bar[k][1]; |
841 | b = bars[k][2]; | 901 | b = bars[fh->input].bar[k][2]; |
842 | is_yuv = 0; | 902 | is_yuv = 0; |
843 | 903 | ||
844 | switch (fh->fmt->fourcc) { | 904 | switch (fh->fmt->fourcc) { |
@@ -871,11 +931,40 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
871 | } | 931 | } |
872 | } | 932 | } |
873 | 933 | ||
934 | } | ||
935 | |||
936 | /*FIXME: This seems to be generic enough to be at videodev2 */ | ||
937 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
938 | struct v4l2_format *f) | ||
939 | { | ||
940 | struct vivi_fh *fh = priv; | ||
941 | struct videobuf_queue *q = &fh->vb_vidq; | ||
942 | |||
943 | int ret = vidioc_try_fmt_vid_cap(file, fh, f); | ||
944 | if (ret < 0) | ||
945 | return ret; | ||
946 | |||
947 | mutex_lock(&q->vb_lock); | ||
948 | |||
949 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | ||
950 | dprintk(fh->dev, 1, "%s queue busy\n", __func__); | ||
951 | ret = -EBUSY; | ||
952 | goto out; | ||
953 | } | ||
954 | |||
955 | fh->fmt = get_format(f); | ||
956 | fh->width = f->fmt.pix.width; | ||
957 | fh->height = f->fmt.pix.height; | ||
958 | fh->vb_vidq.field = f->fmt.pix.field; | ||
959 | fh->type = f->type; | ||
960 | |||
961 | precalculate_bars(fh); | ||
962 | |||
874 | ret = 0; | 963 | ret = 0; |
875 | out: | 964 | out: |
876 | mutex_unlock(&q->vb_lock); | 965 | mutex_unlock(&q->vb_lock); |
877 | 966 | ||
878 | return (ret); | 967 | return ret; |
879 | } | 968 | } |
880 | 969 | ||
881 | static int vidioc_reqbufs(struct file *file, void *priv, | 970 | static int vidioc_reqbufs(struct file *file, void *priv, |
@@ -950,27 +1039,36 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) | |||
950 | static int vidioc_enum_input(struct file *file, void *priv, | 1039 | static int vidioc_enum_input(struct file *file, void *priv, |
951 | struct v4l2_input *inp) | 1040 | struct v4l2_input *inp) |
952 | { | 1041 | { |
953 | if (inp->index != 0) | 1042 | if (inp->index >= NUM_INPUTS) |
954 | return -EINVAL; | 1043 | return -EINVAL; |
955 | 1044 | ||
956 | inp->type = V4L2_INPUT_TYPE_CAMERA; | 1045 | inp->type = V4L2_INPUT_TYPE_CAMERA; |
957 | inp->std = V4L2_STD_525_60; | 1046 | inp->std = V4L2_STD_525_60; |
958 | strcpy(inp->name, "Camera"); | 1047 | sprintf(inp->name, "Camera %u", inp->index); |
959 | 1048 | ||
960 | return (0); | 1049 | return (0); |
961 | } | 1050 | } |
962 | 1051 | ||
963 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 1052 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
964 | { | 1053 | { |
965 | *i = 0; | 1054 | struct vivi_fh *fh = priv; |
1055 | struct vivi_dev *dev = fh->dev; | ||
1056 | |||
1057 | *i = dev->input; | ||
966 | 1058 | ||
967 | return (0); | 1059 | return (0); |
968 | } | 1060 | } |
969 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 1061 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) |
970 | { | 1062 | { |
971 | if (i > 0) | 1063 | struct vivi_fh *fh = priv; |
1064 | struct vivi_dev *dev = fh->dev; | ||
1065 | |||
1066 | if (i >= NUM_INPUTS) | ||
972 | return -EINVAL; | 1067 | return -EINVAL; |
973 | 1068 | ||
1069 | dev->input = i; | ||
1070 | precalculate_bars(fh); | ||
1071 | |||
974 | return (0); | 1072 | return (0); |
975 | } | 1073 | } |
976 | 1074 | ||