summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Huang <kevinh@nvidia.com>2011-10-06 15:48:52 -0700
committerRohan Somvanshi <rsomvanshi@nvidia.com>2011-10-11 05:08:08 -0700
commit8a2ec9a20d88db2f96e17cb7136d81560b989542 (patch)
tree3d2a572776b899ea9b70386cbbf0c8dc634e7325
parent0adbe7449cf2a8a4752077824649a113e967bf90 (diff)
video: tegra: hdmi: Add support to HDMI test in driver.
Test function is invoked by hdmi test module to test DC1, HDMI and EDID modules. Bug 834332 Change-Id: Ib67069ce2b8969ea13ebb1f4ac15a28d62da8adb Reviewed-on: http://git-master/r/56482 Reviewed-by: Kevin Huang (Eng-SW) <kevinh@nvidia.com> Tested-by: Kevin Huang (Eng-SW) <kevinh@nvidia.com> Reviewed-by: Jon Mayo <jmayo@nvidia.com>
-rw-r--r--drivers/video/tegra/dc/edid.c74
-rw-r--r--drivers/video/tegra/dc/edid.h2
-rw-r--r--drivers/video/tegra/dc/hdmi.c78
3 files changed, 138 insertions, 16 deletions
diff --git a/drivers/video/tegra/dc/edid.c b/drivers/video/tegra/dc/edid.c
index 5c0e26e2677d..21445f95263a 100644
--- a/drivers/video/tegra/dc/edid.c
+++ b/drivers/video/tegra/dc/edid.c
@@ -329,6 +329,80 @@ static void data_release(struct kref *ref)
vfree(data);
}
+int tegra_edid_get_monspecs_test(struct tegra_edid *edid,
+ struct fb_monspecs *specs, unsigned char *edid_ptr)
+{
+ int i, j, ret;
+ int extension_blocks;
+ struct tegra_edid_pvt *new_data, *old_data;
+ u8 *data;
+
+ new_data = vmalloc(SZ_32K + sizeof(struct tegra_edid_pvt));
+ if (!new_data)
+ return -ENOMEM;
+
+ kref_init(&new_data->refcnt);
+
+ new_data->support_stereo = 0;
+
+ data = new_data->dc_edid.buf;
+ memcpy(data, edid_ptr, 128);
+
+ memset(specs, 0x0, sizeof(struct fb_monspecs));
+ memset(&new_data->eld, 0x0, sizeof(new_data->eld));
+ fb_edid_to_monspecs(data, specs);
+ if (specs->modedb == NULL) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ memcpy(new_data->eld.monitor_name, specs->monitor,
+ sizeof(specs->monitor));
+
+ new_data->eld.mnl = strlen(new_data->eld.monitor_name) + 1;
+ new_data->eld.product_id[0] = data[0x8];
+ new_data->eld.product_id[1] = data[0x9];
+ new_data->eld.manufacture_id[0] = data[0xA];
+ new_data->eld.manufacture_id[1] = data[0xB];
+
+ extension_blocks = data[0x7e];
+ for (i = 1; i <= extension_blocks; i++) {
+ memcpy(data+128, edid_ptr+128, 128);
+
+ if (data[i * 128] == 0x2) {
+ fb_edid_add_monspecs(data + i * 128, specs);
+
+ tegra_edid_parse_ext_block(data + i * 128,
+ data[i * 128 + 2], new_data);
+
+ if (new_data->support_stereo) {
+ for (j = 0; j < specs->modedb_len; j++) {
+ if (tegra_edid_mode_support_stereo(
+ &specs->modedb[j]))
+ specs->modedb[j].vmode |=
+ FB_VMODE_STEREO_FRAME_PACK;
+ }
+ }
+ }
+ }
+
+ new_data->dc_edid.len = i * 128;
+
+ mutex_lock(&edid->lock);
+ old_data = edid->data;
+ edid->data = new_data;
+ mutex_unlock(&edid->lock);
+
+ if (old_data)
+ kref_put(&old_data->refcnt, data_release);
+
+ tegra_edid_dump(edid);
+ return 0;
+fail:
+ vfree(new_data);
+ return ret;
+}
+
int tegra_edid_get_monspecs(struct tegra_edid *edid, struct fb_monspecs *specs)
{
int i;
diff --git a/drivers/video/tegra/dc/edid.h b/drivers/video/tegra/dc/edid.h
index 773fa0afd18c..88438e4f1f55 100644
--- a/drivers/video/tegra/dc/edid.h
+++ b/drivers/video/tegra/dc/edid.h
@@ -50,6 +50,8 @@ struct tegra_edid_hdmi_eld {
struct tegra_edid *tegra_edid_create(int bus);
void tegra_edid_destroy(struct tegra_edid *edid);
+int tegra_edid_get_monspecs_test(struct tegra_edid *edid,
+ struct fb_monspecs *specs, u8 *edid_ptr);
int tegra_edid_get_monspecs(struct tegra_edid *edid, struct fb_monspecs *specs);
int tegra_edid_get_eld(struct tegra_edid *edid, struct tegra_edid_hdmi_eld *elddata);
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c
index c9cd767725df..db56e817a5e0 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -355,7 +355,7 @@ const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
{25200000, 11760, 26250, 25000},
{27000000, 11760, 28125, 25000},
{74250000, 9408, 61875, 20000},
- {148500000, 9408, 123750,20000},
+ {148500000, 9408, 123750, 20000},
{0, 0, 0},
};
@@ -740,6 +740,66 @@ static bool tegra_dc_hdmi_hpd(struct tegra_dc *dc)
(sense == TEGRA_DC_OUT_HOTPLUG_LOW && !level);
}
+
+bool tegra_dc_hdmi_detect_config(struct tegra_dc *dc,
+ struct fb_monspecs *specs)
+{
+ struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+
+ /* monitors like to lie about these but they are still useful for
+ * detecting aspect ratios
+ */
+ dc->out->h_size = specs->max_x * 1000;
+ dc->out->v_size = specs->max_y * 1000;
+
+ hdmi->dvi = !(specs->misc & FB_MISC_HDMI);
+
+ tegra_fb_update_monspecs(dc->fb, specs, tegra_dc_hdmi_mode_filter);
+ hdmi->hpd_switch.state = 0;
+ switch_set_state(&hdmi->hpd_switch, 1);
+ dev_info(&dc->ndev->dev, "display detected\n");
+
+ dc->connected = true;
+ tegra_dc_ext_process_hotplug(dc->ndev->id);
+}
+
+/* This function is used to enable DC1 and HDMI for the purpose of testing. */
+bool tegra_dc_hdmi_detect_test(struct tegra_dc *dc, unsigned char *edid_ptr)
+{
+ int err;
+ struct fb_monspecs specs;
+ struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+
+ if (!dc || !hdmi || !edid_ptr) {
+ dev_err(&dc->ndev->dev, "HDMI test failed to get arguments.\n");
+ return false;
+ }
+
+ err = tegra_edid_get_monspecs_test(hdmi->edid, &specs, edid_ptr);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev, "error reading edid\n");
+ goto fail;
+ }
+
+ err = tegra_edid_get_eld(hdmi->edid, &hdmi->eld);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev, "error populating eld\n");
+ goto fail;
+ }
+ hdmi->eld_retrieved = true;
+
+ tegra_dc_hdmi_detect_config(dc, &specs);
+
+ return true;
+
+fail:
+ hdmi->eld_retrieved = false;
+ switch_set_state(&hdmi->hpd_switch, 0);
+ tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0);
+ return false;
+}
+EXPORT_SYMBOL(tegra_dc_hdmi_detect_test);
+
static bool tegra_dc_hdmi_detect(struct tegra_dc *dc)
{
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
@@ -761,22 +821,8 @@ static bool tegra_dc_hdmi_detect(struct tegra_dc *dc)
goto fail;
}
hdmi->eld_retrieved = true;
- /* monitors like to lie about these but they are still useful for
- * detecting aspect ratios
- */
- dc->out->h_size = specs.max_x * 1000;
- dc->out->v_size = specs.max_y * 1000;
-
- hdmi->dvi = !(specs.misc & FB_MISC_HDMI);
-
- tegra_fb_update_monspecs(dc->fb, &specs, tegra_dc_hdmi_mode_filter);
- hdmi->hpd_switch.state = 0;
- switch_set_state(&hdmi->hpd_switch, 1);
- dev_info(&dc->ndev->dev, "display detected\n");
-
- dc->connected = true;
- tegra_dc_ext_process_hotplug(dc->ndev->id);
+ tegra_dc_hdmi_detect_config(dc, &specs);
return true;