From 6488bce942e52f8a47f3e784fcbbe9bf88c8f70d Mon Sep 17 00:00:00 2001 From: Jacob Chen Date: Mon, 28 Aug 2017 13:40:35 +0800 Subject: [PATCH] media: i2c: tc35874x: allow run out-of-box This driver are desgined to be take control by userspace but i'd like to make it support run out-of-box to act as a normal UVC.. Change-Id: I03f4d29efce12e36334e4819cd4323fe4b0d0408 Signed-off-by: Jacob Chen --- drivers/media/i2c/tc35874x.c | 50 ++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/media/i2c/tc35874x.c b/drivers/media/i2c/tc35874x.c index 6cc03d15654b..ae8e0656bcb7 100644 --- a/drivers/media/i2c/tc35874x.c +++ b/drivers/media/i2c/tc35874x.c @@ -79,6 +79,25 @@ static const struct v4l2_dv_timings_cap tc35874x_timings_cap = { V4L2_DV_BT_CAP_CUSTOM) }; +static u8 EDID_1920x1080_60[] = { + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x52, 0x62, 0x88, 0x88, 0x00, 0x88, 0x88, 0x88, + 0x1C, 0x15, 0x01, 0x03, 0x80, 0x00, 0x00, 0x78, + 0x0A, 0x0D, 0xC9, 0xA0, 0x57, 0x47, 0x98, 0x27, + 0x12, 0x48, 0x4C, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3A, + 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, 0x2C, + 0x45, 0x00, 0xC4, 0x8E, 0x21, 0x00, 0x00, 0x1E, + 0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, + 0x6E, 0x28, 0x55, 0x00, 0xC4, 0x8E, 0x21, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x54, + 0x6F, 0x73, 0x68, 0x69, 0x62, 0x61, 0x2D, 0x48, + 0x32, 0x44, 0x0A, 0x20, 0x00, 0x00, 0x00, 0xFD, + 0x00, 0x17, 0x3D, 0x0F, 0x8C, 0x17, 0x00, 0x0A, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x92, +}; + struct tc35874x_state { struct tc35874x_platform_data pdata; struct v4l2_fwnode_bus_mipi_csi2 bus; @@ -112,6 +131,8 @@ struct tc35874x_state { static void tc35874x_enable_interrupts(struct v4l2_subdev *sd, bool cable_connected); static int tc35874x_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd); +static int tc35874x_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings); static inline struct tc35874x_state *to_state(struct v4l2_subdev *sd) { @@ -845,13 +866,15 @@ static void tc35874x_format_change(struct v4l2_subdev *sd) v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__); } else { - if (!v4l2_match_dv_timings(&state->timings, &timings, 0)) + if (!v4l2_match_dv_timings(&state->timings, &timings, 0)) { enable_stream(sd, false); + /* automaticly set timing rather than set by userspace */ + tc35874x_s_dv_timings(sd, &timings); + } - if (debug) - v4l2_print_dv_timings(sd->name, - "tc35874x_format_change: New format: ", - &timings, false); + v4l2_print_dv_timings(sd->name, + "tc35874x_format_change: New format: ", + &timings, false); } if (sd->devnode) @@ -1471,10 +1494,6 @@ static int tc35874x_g_mbus_config(struct v4l2_subdev *sd, static int tc35874x_s_stream(struct v4l2_subdev *sd, int enable) { enable_stream(sd, enable); - if (!enable) { - /* Put all lanes in PL-11 state (STOPSTATE) */ - tc35874x_set_csi(sd); - } return 0; } @@ -1505,9 +1524,6 @@ static int tc35874x_get_fmt(struct v4l2_subdev *sd, struct tc35874x_state *state = to_state(sd); u8 vi_rep = i2c_rd8(sd, VI_REP); - if (format->pad != 0) - return -EINVAL; - format->format.code = state->mbus_fmt_code; format->format.width = state->timings.bt.width; format->format.height = state->timings.bt.height; @@ -1852,6 +1868,7 @@ static int tc35874x_probe(struct i2c_client *client, struct tc35874x_state *state; struct tc35874x_platform_data *pdata = client->dev.platform_data; struct v4l2_subdev *sd; + struct v4l2_subdev_edid def_edid; int err, data; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -1923,7 +1940,7 @@ static int tc35874x_probe(struct i2c_client *client, if (err < 0) goto err_hdl; - state->mbus_fmt_code = MEDIA_BUS_FMT_RGB888_1X24; + state->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_1X16; sd->dev = &client->dev; err = v4l2_async_register_subdev(sd); @@ -1941,6 +1958,13 @@ static int tc35874x_probe(struct i2c_client *client, tc35874x_set_csi_color_space(sd); + def_edid.pad = 0; + def_edid.start_block = 0; + def_edid.blocks = 1; + def_edid.edid = EDID_1920x1080_60; + + tc35874x_s_edid(sd, &def_edid); + tc35874x_init_interrupts(sd); if (state->i2c_client->irq) {