|
45 | 45 | /* Group hold register */
|
46 | 46 | #define IMX335_REG_HOLD 0x3001
|
47 | 47 |
|
| 48 | +/* Test pattern generator */ |
| 49 | +#define IMX335_REG_TPG 0x329e |
| 50 | +#define IMX335_TPG_ALL_000 0 |
| 51 | +#define IMX335_TPG_ALL_FFF 1 |
| 52 | +#define IMX335_TPG_ALL_555 2 |
| 53 | +#define IMX335_TPG_ALL_AAA 3 |
| 54 | +#define IMX335_TPG_TOG_555_AAA 4 |
| 55 | +#define IMX335_TPG_TOG_AAA_555 5 |
| 56 | +#define IMX335_TPG_TOG_000_555 6 |
| 57 | +#define IMX335_TPG_TOG_555_000 7 |
| 58 | +#define IMX335_TPG_TOG_000_FFF 8 |
| 59 | +#define IMX335_TPG_TOG_FFF_000 9 |
| 60 | +#define IMX335_TPG_H_COLOR_BARS 10 |
| 61 | +#define IMX335_TPG_V_COLOR_BARS 11 |
| 62 | + |
48 | 63 | /* Input clock rate */
|
49 | 64 | #define IMX335_INCLK_RATE 24000000
|
50 | 65 |
|
@@ -162,6 +177,38 @@ struct imx335 {
|
162 | 177 | u32 cur_mbus_code;
|
163 | 178 | };
|
164 | 179 |
|
| 180 | +static const char * const imx335_tpg_menu[] = { |
| 181 | + "Disabled", |
| 182 | + "All 000h", |
| 183 | + "All FFFh", |
| 184 | + "All 555h", |
| 185 | + "All AAAh", |
| 186 | + "Toggle 555/AAAh", |
| 187 | + "Toggle AAA/555h", |
| 188 | + "Toggle 000/555h", |
| 189 | + "Toggle 555/000h", |
| 190 | + "Toggle 000/FFFh", |
| 191 | + "Toggle FFF/000h", |
| 192 | + "Horizontal color bars", |
| 193 | + "Vertical color bars", |
| 194 | +}; |
| 195 | + |
| 196 | +static const int imx335_tpg_val[] = { |
| 197 | + IMX335_TPG_ALL_000, |
| 198 | + IMX335_TPG_ALL_000, |
| 199 | + IMX335_TPG_ALL_FFF, |
| 200 | + IMX335_TPG_ALL_555, |
| 201 | + IMX335_TPG_ALL_AAA, |
| 202 | + IMX335_TPG_TOG_555_AAA, |
| 203 | + IMX335_TPG_TOG_AAA_555, |
| 204 | + IMX335_TPG_TOG_000_555, |
| 205 | + IMX335_TPG_TOG_555_000, |
| 206 | + IMX335_TPG_TOG_000_FFF, |
| 207 | + IMX335_TPG_TOG_FFF_000, |
| 208 | + IMX335_TPG_H_COLOR_BARS, |
| 209 | + IMX335_TPG_V_COLOR_BARS, |
| 210 | +}; |
| 211 | + |
165 | 212 | /* Sensor mode registers */
|
166 | 213 | static const struct imx335_reg mode_2592x1940_regs[] = {
|
167 | 214 | {0x3000, 0x01},
|
@@ -507,6 +554,49 @@ static int imx335_update_exp_gain(struct imx335 *imx335, u32 exposure, u32 gain)
|
507 | 554 | return ret;
|
508 | 555 | }
|
509 | 556 |
|
| 557 | +static int imx335_update_test_pattern(struct imx335 *imx335, u32 pattern_index) |
| 558 | +{ |
| 559 | + int ret; |
| 560 | + |
| 561 | + if (pattern_index >= ARRAY_SIZE(imx335_tpg_val)) |
| 562 | + return -EINVAL; |
| 563 | + |
| 564 | + if (pattern_index) { |
| 565 | + const struct imx335_reg tpg_enable_regs[] = { |
| 566 | + { 0x3148, 0x10 }, |
| 567 | + { 0x3280, 0x00 }, |
| 568 | + { 0x329c, 0x01 }, |
| 569 | + { 0x32a0, 0x11 }, |
| 570 | + { 0x3302, 0x00 }, |
| 571 | + { 0x3303, 0x00 }, |
| 572 | + { 0x336c, 0x00 }, |
| 573 | + }; |
| 574 | + |
| 575 | + ret = imx335_write_reg(imx335, IMX335_REG_TPG, 1, |
| 576 | + imx335_tpg_val[pattern_index]); |
| 577 | + if (ret) |
| 578 | + return ret; |
| 579 | + |
| 580 | + ret = imx335_write_regs(imx335, tpg_enable_regs, |
| 581 | + ARRAY_SIZE(tpg_enable_regs)); |
| 582 | + } else { |
| 583 | + const struct imx335_reg tpg_disable_regs[] = { |
| 584 | + { 0x3148, 0x00 }, |
| 585 | + { 0x3280, 0x01 }, |
| 586 | + { 0x329c, 0x00 }, |
| 587 | + { 0x32a0, 0x10 }, |
| 588 | + { 0x3302, 0x32 }, |
| 589 | + { 0x3303, 0x00 }, |
| 590 | + { 0x336c, 0x01 }, |
| 591 | + }; |
| 592 | + |
| 593 | + ret = imx335_write_regs(imx335, tpg_disable_regs, |
| 594 | + ARRAY_SIZE(tpg_disable_regs)); |
| 595 | + } |
| 596 | + |
| 597 | + return ret; |
| 598 | +} |
| 599 | + |
510 | 600 | /**
|
511 | 601 | * imx335_set_ctrl() - Set subdevice control
|
512 | 602 | * @ctrl: pointer to v4l2_ctrl structure
|
@@ -560,6 +650,10 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
|
560 | 650 |
|
561 | 651 | ret = imx335_update_exp_gain(imx335, exposure, analog_gain);
|
562 | 652 |
|
| 653 | + break; |
| 654 | + case V4L2_CID_TEST_PATTERN: |
| 655 | + ret = imx335_update_test_pattern(imx335, ctrl->val); |
| 656 | + |
563 | 657 | break;
|
564 | 658 | default:
|
565 | 659 | dev_err(imx335->dev, "Invalid control %d\n", ctrl->id);
|
@@ -1117,7 +1211,7 @@ static int imx335_init_controls(struct imx335 *imx335)
|
1117 | 1211 | u32 lpfr;
|
1118 | 1212 | int ret;
|
1119 | 1213 |
|
1120 |
| - ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6); |
| 1214 | + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 7); |
1121 | 1215 | if (ret)
|
1122 | 1216 | return ret;
|
1123 | 1217 |
|
@@ -1151,6 +1245,12 @@ static int imx335_init_controls(struct imx335 *imx335)
|
1151 | 1245 | mode->vblank_max,
|
1152 | 1246 | 1, mode->vblank);
|
1153 | 1247 |
|
| 1248 | + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, |
| 1249 | + &imx335_ctrl_ops, |
| 1250 | + V4L2_CID_TEST_PATTERN, |
| 1251 | + ARRAY_SIZE(imx335_tpg_menu) - 1, |
| 1252 | + 0, 0, imx335_tpg_menu); |
| 1253 | + |
1154 | 1254 | /* Read only controls */
|
1155 | 1255 | imx335->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
|
1156 | 1256 | &imx335_ctrl_ops,
|
|
0 commit comments