diff options
Diffstat (limited to 'drivers/media/video/ov9640.c')
-rw-r--r-- | drivers/media/video/ov9640.c | 107 |
1 files changed, 69 insertions, 38 deletions
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index c81ae2192887..47bf60ceb7a2 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c | |||
@@ -154,19 +154,10 @@ static const struct ov9640_reg ov9640_regs_rgb[] = { | |||
154 | { OV9640_MTXS, 0x65 }, | 154 | { OV9640_MTXS, 0x65 }, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | /* | 157 | static enum v4l2_mbus_pixelcode ov9640_codes[] = { |
158 | * TODO: this sensor also supports RGB555 and RGB565 formats, but support for | 158 | V4L2_MBUS_FMT_YUYV8_2X8_BE, |
159 | * them has not yet been sufficiently tested and so it is not included with | 159 | V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, |
160 | * this version of the driver. To test and debug these formats add two entries | 160 | V4L2_MBUS_FMT_RGB565_2X8_LE, |
161 | * to the below array, see ov722x.c for an example. | ||
162 | */ | ||
163 | static const struct soc_camera_data_format ov9640_fmt_lists[] = { | ||
164 | { | ||
165 | .name = "UYVY", | ||
166 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
167 | .depth = 16, | ||
168 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
169 | }, | ||
170 | }; | 161 | }; |
171 | 162 | ||
172 | static const struct v4l2_queryctrl ov9640_controls[] = { | 163 | static const struct v4l2_queryctrl ov9640_controls[] = { |
@@ -434,20 +425,22 @@ static void ov9640_res_roundup(u32 *width, u32 *height) | |||
434 | } | 425 | } |
435 | 426 | ||
436 | /* Prepare necessary register changes depending on color encoding */ | 427 | /* Prepare necessary register changes depending on color encoding */ |
437 | static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt) | 428 | static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code, |
429 | struct ov9640_reg_alt *alt) | ||
438 | { | 430 | { |
439 | switch (pixfmt) { | 431 | switch (code) { |
440 | case V4L2_PIX_FMT_UYVY: | 432 | default: |
433 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | ||
441 | alt->com12 = OV9640_COM12_YUV_AVG; | 434 | alt->com12 = OV9640_COM12_YUV_AVG; |
442 | alt->com13 = OV9640_COM13_Y_DELAY_EN | | 435 | alt->com13 = OV9640_COM13_Y_DELAY_EN | |
443 | OV9640_COM13_YUV_DLY(0x01); | 436 | OV9640_COM13_YUV_DLY(0x01); |
444 | break; | 437 | break; |
445 | case V4L2_PIX_FMT_RGB555: | 438 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: |
446 | alt->com7 = OV9640_COM7_RGB; | 439 | alt->com7 = OV9640_COM7_RGB; |
447 | alt->com13 = OV9640_COM13_RGB_AVG; | 440 | alt->com13 = OV9640_COM13_RGB_AVG; |
448 | alt->com15 = OV9640_COM15_RGB_555; | 441 | alt->com15 = OV9640_COM15_RGB_555; |
449 | break; | 442 | break; |
450 | case V4L2_PIX_FMT_RGB565: | 443 | case V4L2_MBUS_FMT_RGB565_2X8_LE: |
451 | alt->com7 = OV9640_COM7_RGB; | 444 | alt->com7 = OV9640_COM7_RGB; |
452 | alt->com13 = OV9640_COM13_RGB_AVG; | 445 | alt->com13 = OV9640_COM13_RGB_AVG; |
453 | alt->com15 = OV9640_COM15_RGB_565; | 446 | alt->com15 = OV9640_COM15_RGB_565; |
@@ -456,8 +449,8 @@ static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt) | |||
456 | } | 449 | } |
457 | 450 | ||
458 | /* Setup registers according to resolution and color encoding */ | 451 | /* Setup registers according to resolution and color encoding */ |
459 | static int ov9640_write_regs(struct i2c_client *client, | 452 | static int ov9640_write_regs(struct i2c_client *client, u32 width, |
460 | u32 width, u32 pixfmt, struct ov9640_reg_alt *alts) | 453 | enum v4l2_mbus_pixelcode code, struct ov9640_reg_alt *alts) |
461 | { | 454 | { |
462 | const struct ov9640_reg *ov9640_regs, *matrix_regs; | 455 | const struct ov9640_reg *ov9640_regs, *matrix_regs; |
463 | int ov9640_regs_len, matrix_regs_len; | 456 | int ov9640_regs_len, matrix_regs_len; |
@@ -500,7 +493,7 @@ static int ov9640_write_regs(struct i2c_client *client, | |||
500 | } | 493 | } |
501 | 494 | ||
502 | /* select color matrix configuration for given color encoding */ | 495 | /* select color matrix configuration for given color encoding */ |
503 | if (pixfmt == V4L2_PIX_FMT_UYVY) { | 496 | if (code == V4L2_MBUS_FMT_YUYV8_2X8_BE) { |
504 | matrix_regs = ov9640_regs_yuv; | 497 | matrix_regs = ov9640_regs_yuv; |
505 | matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); | 498 | matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); |
506 | } else { | 499 | } else { |
@@ -562,15 +555,17 @@ static int ov9640_prog_dflt(struct i2c_client *client) | |||
562 | } | 555 | } |
563 | 556 | ||
564 | /* set the format we will capture in */ | 557 | /* set the format we will capture in */ |
565 | static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 558 | static int ov9640_s_fmt(struct v4l2_subdev *sd, |
559 | struct v4l2_mbus_framefmt *mf) | ||
566 | { | 560 | { |
567 | struct i2c_client *client = sd->priv; | 561 | struct i2c_client *client = sd->priv; |
568 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
569 | struct ov9640_reg_alt alts = {0}; | 562 | struct ov9640_reg_alt alts = {0}; |
563 | enum v4l2_colorspace cspace; | ||
564 | enum v4l2_mbus_pixelcode code = mf->code; | ||
570 | int ret; | 565 | int ret; |
571 | 566 | ||
572 | ov9640_res_roundup(&pix->width, &pix->height); | 567 | ov9640_res_roundup(&mf->width, &mf->height); |
573 | ov9640_alter_regs(pix->pixelformat, &alts); | 568 | ov9640_alter_regs(mf->code, &alts); |
574 | 569 | ||
575 | ov9640_reset(client); | 570 | ov9640_reset(client); |
576 | 571 | ||
@@ -578,19 +573,57 @@ static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
578 | if (ret) | 573 | if (ret) |
579 | return ret; | 574 | return ret; |
580 | 575 | ||
581 | return ov9640_write_regs(client, pix->width, pix->pixelformat, &alts); | 576 | switch (code) { |
577 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: | ||
578 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | ||
579 | cspace = V4L2_COLORSPACE_SRGB; | ||
580 | break; | ||
581 | default: | ||
582 | code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | ||
583 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | ||
584 | cspace = V4L2_COLORSPACE_JPEG; | ||
585 | } | ||
586 | |||
587 | ret = ov9640_write_regs(client, mf->width, code, &alts); | ||
588 | if (!ret) { | ||
589 | mf->code = code; | ||
590 | mf->colorspace = cspace; | ||
591 | } | ||
592 | |||
593 | return ret; | ||
582 | } | 594 | } |
583 | 595 | ||
584 | static int ov9640_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 596 | static int ov9640_try_fmt(struct v4l2_subdev *sd, |
597 | struct v4l2_mbus_framefmt *mf) | ||
585 | { | 598 | { |
586 | struct v4l2_pix_format *pix = &f->fmt.pix; | 599 | ov9640_res_roundup(&mf->width, &mf->height); |
587 | 600 | ||
588 | ov9640_res_roundup(&pix->width, &pix->height); | 601 | mf->field = V4L2_FIELD_NONE; |
589 | pix->field = V4L2_FIELD_NONE; | 602 | |
603 | switch (mf->code) { | ||
604 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: | ||
605 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | ||
606 | mf->colorspace = V4L2_COLORSPACE_SRGB; | ||
607 | break; | ||
608 | default: | ||
609 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | ||
610 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | ||
611 | mf->colorspace = V4L2_COLORSPACE_JPEG; | ||
612 | } | ||
590 | 613 | ||
591 | return 0; | 614 | return 0; |
592 | } | 615 | } |
593 | 616 | ||
617 | static int ov9640_enum_fmt(struct v4l2_subdev *sd, int index, | ||
618 | enum v4l2_mbus_pixelcode *code) | ||
619 | { | ||
620 | if ((unsigned int)index >= ARRAY_SIZE(ov9640_codes)) | ||
621 | return -EINVAL; | ||
622 | |||
623 | *code = ov9640_codes[index]; | ||
624 | return 0; | ||
625 | } | ||
626 | |||
594 | static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 627 | static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
595 | { | 628 | { |
596 | a->c.left = 0; | 629 | a->c.left = 0; |
@@ -637,9 +670,6 @@ static int ov9640_video_probe(struct soc_camera_device *icd, | |||
637 | goto err; | 670 | goto err; |
638 | } | 671 | } |
639 | 672 | ||
640 | icd->formats = ov9640_fmt_lists; | ||
641 | icd->num_formats = ARRAY_SIZE(ov9640_fmt_lists); | ||
642 | |||
643 | /* | 673 | /* |
644 | * check and show product ID and manufacturer ID | 674 | * check and show product ID and manufacturer ID |
645 | */ | 675 | */ |
@@ -702,11 +732,12 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = { | |||
702 | }; | 732 | }; |
703 | 733 | ||
704 | static struct v4l2_subdev_video_ops ov9640_video_ops = { | 734 | static struct v4l2_subdev_video_ops ov9640_video_ops = { |
705 | .s_stream = ov9640_s_stream, | 735 | .s_stream = ov9640_s_stream, |
706 | .s_fmt = ov9640_s_fmt, | 736 | .s_mbus_fmt = ov9640_s_fmt, |
707 | .try_fmt = ov9640_try_fmt, | 737 | .try_mbus_fmt = ov9640_try_fmt, |
708 | .cropcap = ov9640_cropcap, | 738 | .enum_mbus_fmt = ov9640_enum_fmt, |
709 | .g_crop = ov9640_g_crop, | 739 | .cropcap = ov9640_cropcap, |
740 | .g_crop = ov9640_g_crop, | ||
710 | 741 | ||
711 | }; | 742 | }; |
712 | 743 | ||