Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

media: i2c: rotate 180 for some OV02C10 modules #186

Merged
merged 1 commit into from
Sep 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions drivers/media/i2c/ov02c10.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
#define OV02C10_DGTL_GAIN_STEP 1
#define OV02C10_DGTL_GAIN_DEFAULT 0x0400

/* Rotate */
#define OV02C10_ROTATE_CONTROL 0x3820
#define OV02C10_ISP_X_WIN_CONTROL 0x3811
#define OV02C10_ISP_Y_WIN_CONTROL 0x3813
#define OV02C10_CONFIG_ROTATE 0x18

/* Test Pattern Control */
#define OV02C10_REG_TEST_PATTERN 0x4503
#define OV02C10_TEST_PATTERN_ENABLE BIT(7)
Expand All @@ -61,6 +67,14 @@ enum {
OV02C10_LINK_FREQ_400MHZ_INDEX,
};

enum module_names {
MODULE_EMPTY = 0,
MODULE_2BG203N3,
MODULE_CJFME32,
/* etc. */
MODULE_MAX
};

struct ov02c10_reg {
u16 address;
u8 val;
Expand Down Expand Up @@ -130,6 +144,15 @@ struct mipi_camera_link_ssdb {
u8 reserved2[13];
} __packed;

/*
* 822ace8f-2814-4174-a56b-5f029fe079ee
* This _DSM GUID returns a string from the sensor device, which acts as a
* module identifier.
*/
static const guid_t cio2_sensor_module_guid =
GUID_INIT(0x822ace8f, 0x2814, 0x4174,
0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);

static const struct ov02c10_reg mipi_data_rate_960mbps[] = {
};

Expand Down Expand Up @@ -598,6 +621,12 @@ static const char * const ov02c10_test_pattern_menu[] = {
"Color Bar type 4",
};

static const char * const ov02c10_module_names[] = {
[MODULE_EMPTY] = "",
[MODULE_CJFME32] = "CJFME32",
[MODULE_2BG203N3] = "2BG203N3",
};

static const s64 link_freq_menu_items[] = {
OV02C10_LINK_FREQ_400MHZ,
};
Expand Down Expand Up @@ -667,6 +696,9 @@ struct ov02c10 {

/* Streaming on/off */
bool streaming;

/* Module name index */
u8 module_name_index;
};

static inline struct ov02c10 *to_ov02c10(struct v4l2_subdev *subdev)
Expand Down Expand Up @@ -936,6 +968,51 @@ static int ov02c10_start_streaming(struct ov02c10 *ov02c10)
if (ret)
return ret;

if ((ov02c10->module_name_index == MODULE_CJFME32) ||
(ov02c10->module_name_index == MODULE_2BG203N3)) {
u32 rotateReg, shiftXReg, shiftYReg;

ret = ov02c10_read_reg(ov02c10, OV02C10_ROTATE_CONTROL, 1,
&rotateReg);
if (ret)
dev_err(&client->dev, "OV02C10_ROTATE_CONTROL read Fail = 0x%x",
rotateReg);

ret = ov02c10_read_reg(ov02c10, OV02C10_ISP_X_WIN_CONTROL, 1,
&shiftXReg);
if (ret)
dev_err(&client->dev, "OV02C10_ISP_X_WIN_CONTROL read Fail = 0x%x",
shiftXReg);

ret = ov02c10_read_reg(ov02c10, OV02C10_ISP_Y_WIN_CONTROL, 1,
&shiftYReg);
if (ret)
dev_err(&client->dev, "OV02C10_ISP_Y_WIN_CONTROL read Fail = 0x%x",
shiftYReg);

rotateReg ^= OV02C10_CONFIG_ROTATE;
shiftXReg = shiftXReg - 1;
shiftYReg = shiftYReg - 1;

ret = ov02c10_write_reg(ov02c10, OV02C10_ROTATE_CONTROL, 1,
rotateReg);
if (ret)
dev_err(&client->dev, "OV02C10_ROTATE_CONTROL write Fail = 0x%x",
rotateReg);

ret = ov02c10_write_reg(ov02c10, OV02C10_ISP_X_WIN_CONTROL, 1,
shiftXReg);
if (ret)
dev_err(&client->dev, "OV02C10_ISP_X_WIN_CONTROL write Fail = 0x%x",
shiftXReg);

ret = ov02c10_write_reg(ov02c10, OV02C10_ISP_Y_WIN_CONTROL, 1,
shiftYReg);
if (ret)
dev_err(&client->dev, "OV02C10_ISP_Y_WIN_CONTROL write Fail = 0x%x",
shiftYReg);
}

ret = ov02c10_write_reg(ov02c10, OV02C10_REG_MODE_SELECT, 1,
OV02C10_MODE_STREAMING);
if (ret)
Expand Down Expand Up @@ -1309,6 +1386,31 @@ static void ov02c10_remove(struct i2c_client *client)
#endif
}

static int ov02c10_read_module_name(struct ov02c10 *ov02c10)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov02c10->sd);
struct device *dev = &client->dev;
int i = 0;
union acpi_object *obj;

obj = acpi_evaluate_dsm_typed(ACPI_COMPANION(dev)->handle,
&cio2_sensor_module_guid, 0x00,
0x01, NULL, ACPI_TYPE_STRING);

ov02c10->module_name_index = 0;
if (obj && obj->string.type == ACPI_TYPE_STRING) {
for (i = 1; i < ARRAY_SIZE(ov02c10_module_names); i++) {
if (!strcmp(ov02c10_module_names[i], obj->string.pointer)) {
ov02c10->module_name_index = i;
break;
}
}
}
ACPI_FREE(obj);

return 0;
}

static int ov02c10_probe(struct i2c_client *client)
{
struct ov02c10 *ov02c10;
Expand All @@ -1319,6 +1421,8 @@ static int ov02c10_probe(struct i2c_client *client)
return -ENOMEM;

v4l2_i2c_subdev_init(&ov02c10->sd, client, &ov02c10_subdev_ops);
ov02c10_read_module_name(ov02c10);

#if IS_ENABLED(CONFIG_INTEL_VSC)
ov02c10->mipi_lanes = OV02C10_DATA_LANES;
ov02c10->conf.lane_num = ov02c10->mipi_lanes;
Expand Down