summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/ext
diff options
context:
space:
mode:
authorRobert Morell <rmorell@nvidia.com>2011-08-24 16:52:56 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:48:45 -0800
commit97d5a84a90ab41cab1c49c8a259aa84799458455 (patch)
treea1175aaa2f54966774159523e2a7416557064493 /drivers/video/tegra/dc/ext
parentf237f2f6f25be739efaacc254a74d1a97b942d62 (diff)
video: tegra: Implement EDID query
This change implements the TEGRA_DC_EXT_CONTROL_GET_OUTPUT_EDID ioctl in the dc_ext interface. It first adds a way for the tegra dc EDID module to export EDID data safely, without the risk of reading an incomplete or corrupted EDID in the presence of hotplug, by moving the actual data to a substructure with a lifetime maintained by a kref. Then, that support is plumbed through the hdmi block (which is currently the only way to get at the EDID) and out to userspace. Signed-off-by: Robert Morell <rmorell@nvidia.com> Bug 817119 Original-Change-Id: I78cd170e15322011b428cb71ffad2c0c3ea058ac Reviewed-on: http://git-master/r/49127 Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com> Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com> Rebase-Id: Rafafc0a6fbacda5494b12162ad99a8c70ceeb2e0
Diffstat (limited to 'drivers/video/tegra/dc/ext')
-rw-r--r--drivers/video/tegra/dc/ext/control.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/drivers/video/tegra/dc/ext/control.c b/drivers/video/tegra/dc/ext/control.c
index 1bf0b2de0711..f6fb3c0d9006 100644
--- a/drivers/video/tegra/dc/ext/control.c
+++ b/drivers/video/tegra/dc/ext/control.c
@@ -64,8 +64,43 @@ get_output_properties(struct tegra_dc_ext_control_output_properties *properties)
static int get_output_edid(struct tegra_dc_ext_control_output_edid *edid)
{
- /* XXX implement me */
- return -ENOTSUPP;
+ struct tegra_dc *dc;
+ size_t user_size = edid->size;
+ struct tegra_dc_edid *dc_edid = NULL;
+ int ret;
+
+ /* TODO: this should be more dynamic */
+ if (edid->handle > 2)
+ return -EINVAL;
+
+ dc = tegra_dc_get_dc(edid->handle);
+
+ dc_edid = tegra_dc_get_edid(dc);
+ if (IS_ERR(dc_edid))
+ return PTR_ERR(dc_edid);
+
+ if (!dc_edid) {
+ edid->size = 0;
+ } else {
+ edid->size = dc_edid->len;
+
+ if (user_size < edid->size) {
+ ret = -EFBIG;
+ goto done;
+ }
+
+ if (copy_to_user(edid->data, dc_edid->buf, edid->size)) {
+ ret = -EFAULT;
+ goto done;
+ }
+
+ }
+
+done:
+ if (dc_edid)
+ tegra_dc_put_edid(dc_edid);
+
+ return ret;
}
static int set_event_mask(struct tegra_dc_ext_control_user *user, u32 mask)