diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-07-26 07:02:50 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-09-13 15:29:07 -0400 |
commit | e9a50e4c2dd8ca871c20480e49125ef67da84722 (patch) | |
tree | d9cc020b0479d2de5a9abbccb2ffe0990bef4481 /drivers/media/i2c/mt9v032.c | |
parent | 41a33a00e82a897f973a98355e43e78efaa292e1 (diff) |
[media] mt9v032: Provide link frequency control
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/i2c/mt9v032.c')
-rw-r--r-- | drivers/media/i2c/mt9v032.c | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 2203a6f52e48..bf591b891a74 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #define MT9V032_PIXEL_ARRAY_HEIGHT 492 | 29 | #define MT9V032_PIXEL_ARRAY_HEIGHT 492 |
30 | #define MT9V032_PIXEL_ARRAY_WIDTH 782 | 30 | #define MT9V032_PIXEL_ARRAY_WIDTH 782 |
31 | 31 | ||
32 | #define MT9V032_SYSCLK_FREQ_DEF 26600000 | ||
33 | |||
32 | #define MT9V032_CHIP_VERSION 0x00 | 34 | #define MT9V032_CHIP_VERSION 0x00 |
33 | #define MT9V032_CHIP_ID_REV1 0x1311 | 35 | #define MT9V032_CHIP_ID_REV1 0x1311 |
34 | #define MT9V032_CHIP_ID_REV3 0x1313 | 36 | #define MT9V032_CHIP_ID_REV3 0x1313 |
@@ -122,13 +124,18 @@ struct mt9v032 { | |||
122 | struct v4l2_mbus_framefmt format; | 124 | struct v4l2_mbus_framefmt format; |
123 | struct v4l2_rect crop; | 125 | struct v4l2_rect crop; |
124 | 126 | ||
125 | struct v4l2_ctrl *pixel_rate; | ||
126 | struct v4l2_ctrl_handler ctrls; | 127 | struct v4l2_ctrl_handler ctrls; |
128 | struct { | ||
129 | struct v4l2_ctrl *link_freq; | ||
130 | struct v4l2_ctrl *pixel_rate; | ||
131 | }; | ||
127 | 132 | ||
128 | struct mutex power_lock; | 133 | struct mutex power_lock; |
129 | int power_count; | 134 | int power_count; |
130 | 135 | ||
131 | struct mt9v032_platform_data *pdata; | 136 | struct mt9v032_platform_data *pdata; |
137 | |||
138 | u32 sysclk; | ||
132 | u16 chip_control; | 139 | u16 chip_control; |
133 | u16 aec_agc; | 140 | u16 aec_agc; |
134 | }; | 141 | }; |
@@ -196,7 +203,7 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) | |||
196 | int ret; | 203 | int ret; |
197 | 204 | ||
198 | if (mt9v032->pdata->set_clock) { | 205 | if (mt9v032->pdata->set_clock) { |
199 | mt9v032->pdata->set_clock(&mt9v032->subdev, EXT_CLK); | 206 | mt9v032->pdata->set_clock(&mt9v032->subdev, mt9v032->sysclk); |
200 | udelay(1); | 207 | udelay(1); |
201 | } | 208 | } |
202 | 209 | ||
@@ -374,7 +381,8 @@ static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032, | |||
374 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | 381 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); |
375 | int ret; | 382 | int ret; |
376 | 383 | ||
377 | ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate, EXT_CLK / hratio); | 384 | ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate, |
385 | mt9v032->sysclk / hratio); | ||
378 | if (ret < 0) | 386 | if (ret < 0) |
379 | dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret); | 387 | dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret); |
380 | } | 388 | } |
@@ -487,6 +495,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) | |||
487 | struct mt9v032 *mt9v032 = | 495 | struct mt9v032 *mt9v032 = |
488 | container_of(ctrl->handler, struct mt9v032, ctrls); | 496 | container_of(ctrl->handler, struct mt9v032, ctrls); |
489 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | 497 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); |
498 | u32 freq; | ||
490 | u16 data; | 499 | u16 data; |
491 | 500 | ||
492 | switch (ctrl->id) { | 501 | switch (ctrl->id) { |
@@ -505,6 +514,16 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) | |||
505 | return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH, | 514 | return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH, |
506 | ctrl->val); | 515 | ctrl->val); |
507 | 516 | ||
517 | case V4L2_CID_PIXEL_RATE: | ||
518 | case V4L2_CID_LINK_FREQ: | ||
519 | if (mt9v032->link_freq == NULL) | ||
520 | break; | ||
521 | |||
522 | freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val]; | ||
523 | mt9v032->pixel_rate->val64 = freq; | ||
524 | mt9v032->sysclk = freq; | ||
525 | break; | ||
526 | |||
508 | case V4L2_CID_TEST_PATTERN: | 527 | case V4L2_CID_TEST_PATTERN: |
509 | switch (ctrl->val) { | 528 | switch (ctrl->val) { |
510 | case 0: | 529 | case 0: |
@@ -683,6 +702,7 @@ static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = { | |||
683 | static int mt9v032_probe(struct i2c_client *client, | 702 | static int mt9v032_probe(struct i2c_client *client, |
684 | const struct i2c_device_id *did) | 703 | const struct i2c_device_id *did) |
685 | { | 704 | { |
705 | struct mt9v032_platform_data *pdata = client->dev.platform_data; | ||
686 | struct mt9v032 *mt9v032; | 706 | struct mt9v032 *mt9v032; |
687 | unsigned int i; | 707 | unsigned int i; |
688 | int ret; | 708 | int ret; |
@@ -699,9 +719,9 @@ static int mt9v032_probe(struct i2c_client *client, | |||
699 | return -ENOMEM; | 719 | return -ENOMEM; |
700 | 720 | ||
701 | mutex_init(&mt9v032->power_lock); | 721 | mutex_init(&mt9v032->power_lock); |
702 | mt9v032->pdata = client->dev.platform_data; | 722 | mt9v032->pdata = pdata; |
703 | 723 | ||
704 | v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 5); | 724 | v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 6); |
705 | 725 | ||
706 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | 726 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, |
707 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | 727 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); |
@@ -715,10 +735,27 @@ static int mt9v032_probe(struct i2c_client *client, | |||
715 | V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN, | 735 | V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN, |
716 | MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1, | 736 | MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1, |
717 | MT9V032_TOTAL_SHUTTER_WIDTH_DEF); | 737 | MT9V032_TOTAL_SHUTTER_WIDTH_DEF); |
738 | |||
718 | mt9v032->pixel_rate = | 739 | mt9v032->pixel_rate = |
719 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | 740 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, |
720 | V4L2_CID_PIXEL_RATE, 0, 0, 1, 0); | 741 | V4L2_CID_PIXEL_RATE, 0, 0, 1, 0); |
721 | 742 | ||
743 | if (pdata && pdata->link_freqs) { | ||
744 | unsigned int def = 0; | ||
745 | |||
746 | for (i = 0; pdata->link_freqs[i]; ++i) { | ||
747 | if (pdata->link_freqs[i] == pdata->link_def_freq) | ||
748 | def = i; | ||
749 | } | ||
750 | |||
751 | mt9v032->link_freq = | ||
752 | v4l2_ctrl_new_int_menu(&mt9v032->ctrls, | ||
753 | &mt9v032_ctrl_ops, | ||
754 | V4L2_CID_LINK_FREQ, i - 1, def, | ||
755 | pdata->link_freqs); | ||
756 | v4l2_ctrl_cluster(2, &mt9v032->link_freq); | ||
757 | } | ||
758 | |||
722 | for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i) | 759 | for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i) |
723 | v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL); | 760 | v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL); |
724 | 761 | ||
@@ -740,6 +777,7 @@ static int mt9v032_probe(struct i2c_client *client, | |||
740 | mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB; | 777 | mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB; |
741 | 778 | ||
742 | mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE; | 779 | mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE; |
780 | mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF; | ||
743 | 781 | ||
744 | v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops); | 782 | v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops); |
745 | mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops; | 783 | mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops; |