drm/glint: initial encoder/dac work, fill in drm_encoder_helper_funcs

Signed-off-by: Matt Turner <mattst88@gmail.com>
diff --git a/drivers/gpu/drm/glint/Makefile b/drivers/gpu/drm/glint/Makefile
index c6bc2bd..661ebbc 100644
--- a/drivers/gpu/drm/glint/Makefile
+++ b/drivers/gpu/drm/glint/Makefile
@@ -3,7 +3,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 ccflags-y := -Iinclude/drm
-glint-y   := glint_crtc.o glint_display.o glint_device.o glint_drv.o \
-	glint_irq.o glint_kms.o
+glint-y   := glint_crtc.o glint_dac.o glint_device.o glint_display.o \
+	glint_drv.o glint_irq.o glint_kms.o
 
 obj-$(CONFIG_DRM_GLINT) += glint.o
diff --git a/drivers/gpu/drm/glint/glint_dac.c b/drivers/gpu/drm/glint/glint_dac.c
new file mode 100644
index 0000000..de495f1
--- /dev/null
+++ b/drivers/gpu/drm/glint/glint_dac.c
@@ -0,0 +1,94 @@
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc_helper.h"
+
+#include <video/pm3fb.h>
+
+#include "glint.h"
+#include "glint_drv.h"
+#include "glint_mode.h"
+
+static void glint_dac_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct glint_device *gdev = dev->dev_private;
+	struct glint_encoder *glint_encoder = to_glint_encoder(encoder);
+
+	if (mode == glint_encoder->last_dpms) /* Don't do unnecesary mode changes. */
+		return;
+
+	glint_encoder->last_dpms = mode;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		WREG_DAC(PM3RD_DACControl, PM3RD_DACControl_DAC_POWER_OFF);
+		break;
+	case DRM_MODE_DPMS_ON:
+		WREG_DAC(PM3RD_DACControl, PM3RD_DACControl_DAC_POWER_OFF);
+		break;
+	}
+}
+
+static bool glint_dac_mode_fixup(struct drm_encoder *encoder,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void glint_dac_mode_set(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+
+}
+
+static void glint_dac_prepare(struct drm_encoder *encoder)
+{
+	glint_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void glint_dac_commit(struct drm_encoder *encoder)
+{
+	glint_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+void glint_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct glint_encoder *glint_encoder = to_glint_encoder(encoder);
+	drm_encoder_cleanup(encoder);
+	kfree(glint_encoder);
+}
+
+static const struct drm_encoder_helper_funcs glint_dac_helper_funcs = {
+	.dpms = glint_dac_dpms,
+	.mode_fixup = glint_dac_mode_fixup,
+	.mode_set = glint_dac_mode_set,
+	.prepare = glint_dac_prepare,
+	.commit = glint_dac_commit,
+};
+
+static const struct drm_encoder_funcs glint_dac_encoder_funcs = {
+	.destroy = glint_encoder_destroy,
+};
+
+struct drm_encoder *glint_dac_init(struct drm_device *dev)
+{
+	struct drm_encoder *encoder;
+	struct glint_encoder *glint_encoder;
+
+	glint_encoder = kzalloc(sizeof(struct glint_encoder), GFP_KERNEL);
+	if (!glint_encoder)
+		return NULL;
+
+	glint_encoder->last_dpms = GLINT_DPMS_CLEARED;
+	encoder = &glint_encoder->base;
+	encoder->possible_crtcs = 0x1;
+
+	drm_encoder_init(dev, encoder, &glint_dac_encoder_funcs, DRM_MODE_ENCODER_DAC);
+	drm_encoder_helper_add(encoder, &glint_dac_helper_funcs);
+
+	return encoder;
+}
diff --git a/drivers/gpu/drm/glint/glint_display.c b/drivers/gpu/drm/glint/glint_display.c
index a8061ea..ecfeef5 100644
--- a/drivers/gpu/drm/glint/glint_display.c
+++ b/drivers/gpu/drm/glint/glint_display.c
@@ -7,6 +7,7 @@
 
 int glint_modeset_init(struct glint_device *gdev)
 {
+	struct drm_encoder *encoder;
 	int i;
 
 	drm_mode_config_init(gdev->ddev);
@@ -22,6 +23,12 @@
 		glint_crtc_init(gdev->ddev, i);
 	}
 
+	encoder = glint_dac_init(gdev->ddev);
+	if (!encoder) {
+		GLINT_ERROR("glint_dac_init failed\n");
+		return -1;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/glint/glint_drv.h b/drivers/gpu/drm/glint/glint_drv.h
index 12fd468..3a2cdba 100644
--- a/drivers/gpu/drm/glint/glint_drv.h
+++ b/drivers/gpu/drm/glint/glint_drv.h
@@ -35,6 +35,9 @@
 				/* glint_crtc.c */
 void glint_crtc_init(struct drm_device *dev, int index);
 
+				/* glint_dac.c */
+struct drm_encoder *glint_dac_init(struct drm_device *dev);
+
 				/* glint_device.c */
 int glint_device_init(struct glint_device *gdev,
 		      struct drm_device *ddev,
diff --git a/drivers/gpu/drm/glint/glint_mode.h b/drivers/gpu/drm/glint/glint_mode.h
index d86e00a..0a125d5 100644
--- a/drivers/gpu/drm/glint/glint_mode.h
+++ b/drivers/gpu/drm/glint/glint_mode.h
@@ -10,6 +10,7 @@
 #define GLINT_DPMS_CLEARED (-1)
 
 #define to_glint_crtc(x) container_of(x, struct glint_crtc, base)
+#define to_glint_encoder(x) container_of(x, struct glint_encoder, base)
 
 struct glint_crtc {
 	struct drm_crtc			base;
@@ -24,4 +25,9 @@
 	struct glint_crtc		*crtcs[2]; /* FIXME: how many CRTCs? */
 };
 
+struct glint_encoder {
+	struct drm_encoder		base;
+	int				last_dpms;
+};
+
 #endif				/* __GLINT_MODE_H__ */