Merge branch 'v4.14.75-ltsi/adv7604.rc1' into v4.14.75-ltsi/rcar-3.9.0
* v4.14.75-ltsi/adv7604.rc1:
media: i2c: adv7604: Add suspend and resume support
media: i2c: adv7604: Fix set_fmt function
media: i2c: adv7604: Add default EDID information
media: i2c: adv7604: Enable decoder control register
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index f289b8a..1addf80 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1,6 +1,7 @@
/*
* adv7604 - Analog Devices ADV7604 video decoder driver
*
+ * Copyright (C) 2017 Renesas Electronics Corp.
* Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
@@ -82,6 +83,8 @@ MODULE_LICENSE("GPL");
#define ADV76XX_OP_SWAP_CB_CR (1 << 0)
+#define ADV7612_CP_VID_ADJ_ENABLE (1 << 7)
+
#define ADV76XX_MAX_ADDRS (3)
enum adv76xx_type {
@@ -321,6 +324,61 @@ static const struct v4l2_event adv76xx_ev_fmt = {
.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
};
+static const __u8 g_edid_data[256] = {
+/* Header information(0-19th byte) */ /* Fixed header pattern */
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+ 0x34, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x0C, 0x01, 0x03,
+/* Basic display parameters(20-24th byte) */
+ 0x80, 0x50, 0x2D, 0x78, 0x0A,
+/* Chromaticity coordinates(25-34th byte) */
+ 0x0D, 0xC9, 0xA0, 0x57, 0x47, 0x98, 0x27, 0x12,
+ 0x48, 0x4C,
+/* Established timing bitmap(35-37th byte) */
+ 0x23, 0x09, 0x00,
+/* Standard timing information(38-53th byte) */
+/* Because they are unused, in this field, all values are 0101h. */
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+/* Descriptor blocks of Descriptor 1(54-71th byte) */
+ 0x01, 0x1D, 0x80, 0x18, 0x71, 0x1C, 0x16, 0x20,
+ 0x58, 0x2C, 0x25, 0x00, 0x20, 0xC2, 0x31, 0x00,
+ 0x00, 0x98,
+/* Descriptor blocks of Descriptor 2(72-89th byte) */
+ 0x8C, 0x0A, 0xD0, 0x8A, 0x20, 0xE0, 0x2D, 0x10,
+ 0x10, 0x3E, 0x96, 0x00, 0x58, 0xC2, 0x21, 0x00,
+ 0x00, 0x18,
+/* Descriptor blocks of Descriptor 3(90-107th byte) */
+ 0x00, 0x00, 0x00, 0xFC, 0x00, 0x4D, 0x59, 0x20,
+ 0x48, 0x44, 0x54, 0x56, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20,
+/* Descriptor blocks of Descriptor 4(108-125th byte) */
+ 0x00, 0x00, 0x00, 0xFD, 0x00, 0x3B, 0x3D, 0x0F,
+ 0x2E, 0x08, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20,
+/* Number of extensions to follow(126th byte) */
+ 0x01, /* Extension enable */
+/* Checksum(127th byte) */
+ 0x65,
+/* CEA EDID Timing Extension Version 3 */
+ 0x02, 0x03, 0x34, 0x40, 0x83, 0x7F, 0x00, 0x00,
+ 0x35, 0x0F, 0x06, 0x07, 0x17, 0x1F, 0x38, 0x1F,
+ 0x07, 0x30, 0x2F, 0x07, 0x72, 0x3F, 0x7F, 0x72,
+ 0x57, 0x7F, 0x00, 0x37, 0x7F, 0x72, 0x67, 0x03,
+ 0x0C, 0x00, 0x10, 0x00, 0x88, 0x2D, 0x4D, 0x82,
+ 0x03, 0x11, 0x12, 0x04, 0x13, 0x10, 0x1F, 0x05,
+ 0x14, 0x22, 0x43, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00,
+ 0x00, 0xFF, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
+};
+
/* ----------------------------------------------------------------------- */
static inline struct adv76xx_state *to_state(struct v4l2_subdev *sd)
@@ -1204,6 +1262,15 @@ static int adv76xx_s_ctrl(struct v4l2_ctrl *ctrl)
&container_of(ctrl->handler, struct adv76xx_state, hdl)->sd;
struct adv76xx_state *state = to_state(sd);
+ int ret;
+ u8 val;
+
+ /* Enable video adjustment first */
+ val = cp_read(sd, 0x3e);
+ val |= ADV7612_CP_VID_ADJ_ENABLE;
+ ret = cp_write(sd, 0x3e, val);
+ if (ret < 0)
+ return ret;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
@@ -1911,6 +1978,11 @@ static int adv76xx_get_format(struct v4l2_subdev *sd,
fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
format->format.code = fmt->code;
} else {
+ struct v4l2_dv_timings timings;
+
+ adv76xx_query_dv_timings(&state->sd, &timings);
+ state->timings = timings;
+
format->format.code = state->format->code;
}
@@ -2738,6 +2810,20 @@ static int adv76xx_core_init(struct v4l2_subdev *sd)
struct adv76xx_state *state = to_state(sd);
const struct adv76xx_chip_info *info = state->info;
struct adv76xx_platform_data *pdata = &state->pdata;
+ int err;
+ struct v4l2_edid g_edid;
+ __u8 edid[256];
+
+ g_edid.pad = 0;
+ g_edid.start_block = 0;
+ g_edid.blocks = 2;
+ memcpy(edid, g_edid_data, 256);
+ g_edid.edid = (__u8 *)edid;
+ err = adv76xx_set_edid(sd, &g_edid);
+ if (err < 0) {
+ v4l2_err(sd, "edid set error %d\n", err);
+ return err;
+ }
hdmi_write(sd, 0x48,
(pdata->disable_pwrdnb ? 0x80 : 0) |
@@ -3441,7 +3527,7 @@ static int adv76xx_probe(struct i2c_client *client,
v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
V4L2_CID_SATURATION, 0, 255, 1, 128);
v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
- V4L2_CID_HUE, 0, 128, 1, 0);
+ V4L2_CID_HUE, 0, 255, 1, 0);
ctrl = v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops,
V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC,
0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC);
@@ -3565,9 +3651,51 @@ static int adv76xx_remove(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
+#ifdef CONFIG_PM_SLEEP
+static int adv76xx_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ u8 value;
+
+ value = io_read(sd, 0x0c) | (u8)0x20;
+ io_write(sd, 0x0c, value);
+
+ return 0;
+}
+
+static int adv76xx_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct adv76xx_state *state = to_state(sd);
+ int i;
+ int ret;
+
+ for (i = 1; i < ADV76XX_PAGE_MAX; ++i) {
+ if (!(BIT(i) & state->info->page_mask))
+ continue;
+ ret = io_write(sd, 0xf2 + i,
+ state->pdata.i2c_addresses[i] << 1);
+ if (ret)
+ return ret;
+ }
+
+ return adv76xx_core_init(sd);
+}
+
+static SIMPLE_DEV_PM_OPS(adv76xx_pm_ops, adv76xx_suspend, adv76xx_resume);
+#define ADV76XX_PM_OPS (&adv76xx_pm_ops)
+#else
+#define ADV76XX_PM_OPS (NULL)
+#endif
+
+/* ----------------------------------------------------------------------- */
+
static struct i2c_driver adv76xx_driver = {
.driver = {
.name = "adv7604",
+ .pm = ADV76XX_PM_OPS,
.of_match_table = of_match_ptr(adv76xx_of_id),
},
.probe = adv76xx_probe,