diff mbox

[RFC,2/4] drm/i915: Add a drm_panel over INTEL_SOC_PMIC

Message ID 1419589410-24365-3-git-send-email-shobhit.kumar@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Kumar, Shobhit Dec. 26, 2014, 10:23 a.m. UTC
This driver just add PANEL_ENABLE/DISABLE control using drm_panel
framework.

Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
---
 drivers/gpu/drm/i915/Makefile           |   1 +
 drivers/gpu/drm/i915/intel_drv.h        |   3 +
 drivers/gpu/drm/i915/intel_panel_pmic.c | 157 ++++++++++++++++++++++++++++++++
 3 files changed, 161 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/intel_panel_pmic.c
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1849ffa..d282476 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -79,6 +79,7 @@  i915-y += dvo_ch7017.o \
 	  intel_i2c.o \
 	  intel_lvds.o \
 	  intel_panel.o \
+	  intel_panel_pmic.o \
 	  intel_sdvo.o \
 	  intel_tv.o
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0088f16..1dab753 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1142,6 +1142,9 @@  extern struct drm_display_mode *intel_find_panel_downclock(
 void intel_backlight_register(struct drm_device *dev);
 void intel_backlight_unregister(struct drm_device *dev);
 
+/* intel_panel_soc_pmic.c */
+struct drm_panel *intel_panel_pmic_init(struct device *dev,
+					struct panel_info *info);
 
 /* intel_psr.c */
 void intel_psr_enable(struct intel_dp *intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_panel_pmic.c b/drivers/gpu/drm/i915/intel_panel_pmic.c
new file mode 100644
index 0000000..28a9f00
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_panel_pmic.c
@@ -0,0 +1,157 @@ 
+/*
+ * Copyright © 2006-2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Shobhit Kumar <shobhit.kumar@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_panel.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include "intel_drv.h"
+
+#define PMIC_PANEL_EN	0x52
+struct panel_pmic {
+	struct drm_panel base;
+	bool prepared;
+	bool enabled;
+
+	/* Panel enable/disable specififc delays */
+	struct panel_info pinfo;
+};
+
+static inline struct panel_pmic *to_panel_pmic(struct drm_panel *panel)
+{
+	return container_of(panel, struct panel_pmic, base);
+}
+
+static int panel_pmic_disable(struct drm_panel *panel)
+{
+	struct panel_pmic *p = to_panel_pmic(panel);
+
+	if (!p->enabled)
+		return 0;
+
+	DRM_DEBUG_KMS("\n");
+
+	/* invoke the pmic driver */
+	intel_soc_pmic_writeb(PMIC_PANEL_EN, 0x00);
+	msleep(p->pinfo.panel_off_delay);
+	msleep(p->pinfo.panel_pwr_cycle_delay);
+
+	p->enabled = false;
+
+	return 0;
+}
+
+static int panel_pmic_unprepare(struct drm_panel *panel)
+{
+	struct panel_pmic *p = to_panel_pmic(panel);
+
+	if (!p->prepared)
+		return 0;
+
+	/* Nothing needed */
+	p->prepared = false;
+
+	return 0;
+}
+
+static int panel_pmic_prepare(struct drm_panel *panel)
+{
+	struct panel_pmic *p = to_panel_pmic(panel);
+
+	if (p->prepared)
+		return 0;
+
+	/* Nothing needed */
+	p->prepared = true;
+
+	return 0;
+}
+
+static int panel_pmic_enable(struct drm_panel *panel)
+{
+	struct panel_pmic *p = to_panel_pmic(panel);
+
+	if (p->enabled)
+		return 0;
+
+	DRM_DEBUG_KMS("\n");
+
+	/* invoke the pmic driver */
+	intel_soc_pmic_writeb(PMIC_PANEL_EN, 0x01);
+	msleep(p->pinfo.panel_on_delay);
+
+	p->enabled = true;
+
+	return 0;
+}
+
+static const struct drm_panel_funcs panel_pmic_funcs = {
+	.disable = panel_pmic_disable,
+	.unprepare = panel_pmic_unprepare,
+	.prepare = panel_pmic_prepare,
+	.enable = panel_pmic_enable,
+};
+
+struct drm_panel *intel_panel_pmic_init(struct device *dev,
+					struct panel_info *info)
+{
+	struct panel_pmic *panel;
+	bool status = false;
+
+	DRM_DEBUG_KMS("\n");
+
+	panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
+	if (!panel)
+		return NULL;
+
+	status = intel_soc_pmic_readb(PMIC_PANEL_EN) ? true : false;
+	panel->enabled = panel->prepared = status;
+
+	memcpy(&panel->pinfo, info, sizeof(struct panel_info));
+
+	drm_panel_init(&panel->base);
+	panel->base.dev = dev;
+	panel->base.funcs = &panel_pmic_funcs;
+
+	drm_panel_add(&panel->base);
+
+	return &panel->base;
+}
+
+int intel_panel_pmic_remove(struct device *dev)
+{
+	struct panel_pmic *panel = dev_get_drvdata(dev);
+
+	DRM_DEBUG_KMS("\n");
+
+	drm_panel_detach(&panel->base);
+	drm_panel_remove(&panel->base);
+
+	panel_pmic_disable(&panel->base);
+
+	kfree(panel);
+	return 0;
+}