Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

media: i2c: ov01a10: Add ov01a10_sensor_cfg struct

Add a struct with some sensor variant (ov01a10 / ov01a1b / ov01a1s)
specific settings.

This is a preparation patch for adding support for the ov01a1s sensor
which uses the same sensor with a different (RGBI) color-filter.

Signed-off-by: Hans de Goede <hansg@kernel.org>
Tested-by: Mehdi Djait <mehdi.djait@linux.intel.com> # Dell XPS 9315
Reviewed-by: Mehdi Djait <mehdi.djait@linux.intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Hans de Goede and committed by
Hans Verkuil
12d3c5ff a9aafc57

+60 -27
+60 -27
drivers/media/i2c/ov01a10.c
··· 88 88 #define OV01A10_REG_TEST_PATTERN CCI_REG8(0x4503) 89 89 #define OV01A10_TEST_PATTERN_ENABLE BIT(7) 90 90 91 - /* 92 - * The native ov01a10 bayer-pattern is GBRG, but there was a driver bug enabling 93 - * hflip/mirroring by default resulting in BGGR. Because of this bug Intel's 94 - * proprietary IPU6 userspace stack expects BGGR. So we report BGGR to not break 95 - * userspace and fix things up by shifting the crop window-x coordinate by 1 96 - * when hflip is *disabled*. 97 - */ 98 - #define OV01A10_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR10_1X10 99 - #define OV01A10_BAYER_PATTERN_SIZE 2 /* 2x2 */ 100 - 101 91 struct ov01a10_link_freq_config { 102 92 const struct reg_sequence *regs; 103 93 int regs_len; ··· 235 245 "dvdd", /* Digital core power */ 236 246 }; 237 247 248 + struct ov01a10_sensor_cfg { 249 + const char *model; 250 + u32 bus_fmt; 251 + int pattern_size; 252 + int border_size; 253 + bool invert_hflip_shift; 254 + bool invert_vflip_shift; 255 + }; 256 + 238 257 struct ov01a10 { 239 258 struct device *dev; 240 259 struct regmap *regmap; 260 + const struct ov01a10_sensor_cfg *cfg; 241 261 struct v4l2_subdev sd; 242 262 struct media_pad pad; 243 263 struct v4l2_ctrl_handler ctrl_handler; ··· 310 310 NULL); 311 311 } 312 312 313 - static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip) 313 + static int ov01a10_set_hflip(struct ov01a10 *ov01a10, bool hflip) 314 314 { 315 315 struct v4l2_rect *crop = ov01a10_get_active_crop(ov01a10); 316 + const struct ov01a10_sensor_cfg *cfg = ov01a10->cfg; 316 317 u32 val, offset; 317 318 int ret = 0; 318 319 319 320 offset = crop->left; 320 - if (!hflip) 321 + if ((hflip ^ cfg->invert_hflip_shift) && cfg->border_size) 321 322 offset++; 322 323 323 324 val = hflip ? 0 : FIELD_PREP(OV01A10_HFLIP_MASK, 0x1); ··· 330 329 return ret; 331 330 } 332 331 333 - static int ov01a10_set_vflip(struct ov01a10 *ov01a10, u32 vflip) 332 + static int ov01a10_set_vflip(struct ov01a10 *ov01a10, bool vflip) 334 333 { 335 334 struct v4l2_rect *crop = ov01a10_get_active_crop(ov01a10); 335 + const struct ov01a10_sensor_cfg *cfg = ov01a10->cfg; 336 336 u32 val, offset; 337 337 int ret = 0; 338 338 339 339 offset = crop->top; 340 - if (vflip) 340 + if ((vflip ^ cfg->invert_vflip_shift) && cfg->border_size) 341 341 offset++; 342 342 343 343 val = vflip ? FIELD_PREP(OV01A10_VFLIP_MASK, 0x1) : 0; ··· 501 499 return ret; 502 500 } 503 501 504 - static void ov01a10_fill_format(struct v4l2_mbus_framefmt *fmt, 502 + static void ov01a10_fill_format(struct ov01a10 *ov01a10, 503 + struct v4l2_mbus_framefmt *fmt, 505 504 unsigned int width, unsigned int height) 506 505 { 507 506 memset(fmt, 0, sizeof(*fmt)); 508 507 fmt->width = width; 509 508 fmt->height = height; 510 - fmt->code = OV01A10_MEDIA_BUS_FMT; 509 + fmt->code = ov01a10->cfg->bus_fmt; 511 510 fmt->field = V4L2_FIELD_NONE; 512 511 fmt->colorspace = V4L2_COLORSPACE_RAW; 513 512 } ··· 628 625 struct v4l2_subdev_format *fmt) 629 626 { 630 627 struct v4l2_rect *crop = v4l2_subdev_state_get_crop(sd_state, fmt->pad); 631 - const int pattern_size = OV01A10_BAYER_PATTERN_SIZE; 632 - const int border_size = OV01A10_BAYER_PATTERN_SIZE; 633 628 struct ov01a10 *ov01a10 = to_ov01a10(sd); 629 + const int pattern_size = ov01a10->cfg->pattern_size; 630 + const int border_size = ov01a10->cfg->border_size; 634 631 unsigned int width, height; 635 632 636 633 width = clamp_val(ALIGN(fmt->format.width, pattern_size), ··· 650 647 crop->height = height; 651 648 } 652 649 653 - ov01a10_fill_format(&fmt->format, width, height); 650 + ov01a10_fill_format(ov01a10, &fmt->format, width, height); 654 651 *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; 655 652 656 653 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) ··· 662 659 static int ov01a10_init_state(struct v4l2_subdev *sd, 663 660 struct v4l2_subdev_state *sd_state) 664 661 { 662 + struct ov01a10 *ov01a10 = to_ov01a10(sd); 663 + 665 664 *v4l2_subdev_state_get_crop(sd_state, 0) = ov01a10_default_crop; 666 - ov01a10_fill_format(v4l2_subdev_state_get_format(sd_state, 0), 665 + ov01a10_fill_format(ov01a10, v4l2_subdev_state_get_format(sd_state, 0), 667 666 OV01A10_DEFAULT_WIDTH, OV01A10_DEFAULT_HEIGHT); 668 667 669 668 return 0; ··· 675 670 struct v4l2_subdev_state *sd_state, 676 671 struct v4l2_subdev_mbus_code_enum *code) 677 672 { 673 + struct ov01a10 *ov01a10 = to_ov01a10(sd); 674 + 678 675 if (code->index > 0) 679 676 return -EINVAL; 680 677 681 - code->code = OV01A10_MEDIA_BUS_FMT; 678 + code->code = ov01a10->cfg->bus_fmt; 682 679 683 680 return 0; 684 681 } ··· 689 682 struct v4l2_subdev_state *sd_state, 690 683 struct v4l2_subdev_frame_size_enum *fse) 691 684 { 692 - const int pattern_size = OV01A10_BAYER_PATTERN_SIZE; 693 - const int border_size = OV01A10_BAYER_PATTERN_SIZE; 685 + struct ov01a10 *ov01a10 = to_ov01a10(sd); 686 + const int pattern_size = ov01a10->cfg->pattern_size; 687 + const int border_size = ov01a10->cfg->border_size; 694 688 695 689 if (fse->index) 696 690 return -EINVAL; ··· 708 700 struct v4l2_subdev_state *state, 709 701 struct v4l2_subdev_selection *sel) 710 702 { 711 - const int border_size = OV01A10_BAYER_PATTERN_SIZE; 703 + struct ov01a10 *ov01a10 = to_ov01a10(sd); 704 + const int border_size = ov01a10->cfg->border_size; 712 705 713 706 switch (sel->target) { 714 707 case V4L2_SEL_TGT_CROP: ··· 740 731 struct v4l2_subdev_state *sd_state, 741 732 struct v4l2_subdev_selection *sel) 742 733 { 743 - const int pattern_size = OV01A10_BAYER_PATTERN_SIZE; 744 - const int border_size = OV01A10_BAYER_PATTERN_SIZE; 745 734 struct ov01a10 *ov01a10 = to_ov01a10(sd); 735 + const int pattern_size = ov01a10->cfg->pattern_size; 736 + const int border_size = ov01a10->cfg->border_size; 746 737 struct v4l2_mbus_framefmt *format; 747 738 struct v4l2_rect *crop; 748 739 struct v4l2_rect rect; ··· 982 973 983 974 static int ov01a10_probe(struct i2c_client *client) 984 975 { 976 + const struct ov01a10_sensor_cfg *cfg; 985 977 struct ov01a10 *ov01a10; 986 978 int ret; 979 + 980 + cfg = device_get_match_data(&client->dev); 981 + if (!cfg) 982 + return -EINVAL; 987 983 988 984 ov01a10 = devm_kzalloc(&client->dev, sizeof(*ov01a10), GFP_KERNEL); 989 985 if (!ov01a10) 990 986 return -ENOMEM; 991 987 992 988 ov01a10->dev = &client->dev; 989 + ov01a10->cfg = cfg; 993 990 994 991 ov01a10->regmap = devm_cci_regmap_init_i2c(client, 16); 995 992 if (IS_ERR(ov01a10->regmap)) 996 993 return PTR_ERR(ov01a10->regmap); 997 994 998 995 v4l2_i2c_subdev_init(&ov01a10->sd, client, &ov01a10_subdev_ops); 996 + /* Override driver->name with actual sensor model */ 997 + v4l2_i2c_subdev_set_name(&ov01a10->sd, client, cfg->model, NULL); 999 998 ov01a10->sd.internal_ops = &ov01a10_internal_ops; 1000 999 1001 1000 ret = ov01a10_check_hwcfg(ov01a10); ··· 1075 1058 ov01a10_power_on, NULL); 1076 1059 1077 1060 #ifdef CONFIG_ACPI 1061 + /* 1062 + * The native ov01a10 bayer-pattern is GBRG, but there was a driver bug enabling 1063 + * hflip/mirroring by default resulting in BGGR. Because of this bug Intel's 1064 + * proprietary IPU6 userspace stack expects BGGR. So we report BGGR to not break 1065 + * userspace and fix things up by shifting the crop window-x coordinate by 1 1066 + * when hflip is *disabled*. 1067 + */ 1068 + static const struct ov01a10_sensor_cfg ov01a10_cfg = { 1069 + .model = "ov01a10", 1070 + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, 1071 + .pattern_size = 2, /* 2x2 */ 1072 + .border_size = 2, 1073 + .invert_hflip_shift = true, 1074 + .invert_vflip_shift = false, 1075 + }; 1076 + 1078 1077 static const struct acpi_device_id ov01a10_acpi_ids[] = { 1079 - { "OVTI01A0" }, 1078 + { "OVTI01A0", (uintptr_t)&ov01a10_cfg }, 1080 1079 { } 1081 1080 }; 1082 1081