From: Wu Zhangjin <wuzhangjin@gmail.com>
This patch adds Video Output Driver, which provides standard interface
to turn on/off the video output of LCD, CRT.
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
.../loongson/lemote-2f/yeeloong_laptop/Kconfig | 8 +
.../loongson/lemote-2f/yeeloong_laptop/Makefile | 1 +
.../lemote-2f/yeeloong_laptop/ec_kb3310b.h | 3 +
.../lemote-2f/yeeloong_laptop/video_output.c | 164 ++++++++++++++++++++
4 files changed, 176 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/loongson/lemote-2f/yeeloong_laptop/video_output.c
diff --git a/arch/mips/loongson/lemote-2f/yeeloong_laptop/Kconfig
b/arch/mips/loongson/lemote-2f/yeeloong_laptop/Kconfig
index 56cb584..c4398ff 100644
--- a/arch/mips/loongson/lemote-2f/yeeloong_laptop/Kconfig
+++ b/arch/mips/loongson/lemote-2f/yeeloong_laptop/Kconfig
@@ -37,4 +37,12 @@ config YEELOONG_HWMON
interface for lm-sensors to monitor the temperatures of CPU and
battery, the PWM of fan, the current, voltage of battery.
+config YEELOONG_VO
+ tristate "Video Output Driver"
+ select VIDEO_OUTPUT_CONTROL
+ default y
+ help
+ This option adds Video Output Driver, which provides standard
+ interface to turn on/off the video output of LCD, CRT.
+
endif
diff --git a/arch/mips/loongson/lemote-2f/yeeloong_laptop/Makefile
b/arch/mips/loongson/lemote-2f/yeeloong_laptop/Makefile
index 73277a8..104670f 100644
--- a/arch/mips/loongson/lemote-2f/yeeloong_laptop/Makefile
+++ b/arch/mips/loongson/lemote-2f/yeeloong_laptop/Makefile
@@ -5,3 +5,4 @@ obj-y += ec_kb3310b.o
obj-$(CONFIG_YEELOONG_BACKLIGHT) += backlight.o
obj-$(CONFIG_YEELOONG_BATTERY) += battery.o
obj-$(CONFIG_YEELOONG_HWMON) += hwmon.o
+obj-$(CONFIG_YEELOONG_VO) += video_output.o
diff --git a/arch/mips/loongson/lemote-2f/yeeloong_laptop/ec_kb3310b.h
b/arch/mips/loongson/lemote-2f/yeeloong_laptop/ec_kb3310b.h
index 674a543..3d08792 100644
--- a/arch/mips/loongson/lemote-2f/yeeloong_laptop/ec_kb3310b.h
+++ b/arch/mips/loongson/lemote-2f/yeeloong_laptop/ec_kb3310b.h
@@ -25,6 +25,9 @@ extern sci_handler yeeloong_report_lid_status;
extern void set_fan_pwm(int value);
extern void set_fan_pwm_enable(int manual);
+extern void lcd_vo_set(int status);
+extern void crt_vo_set(int status);
+
#define SCI_IRQ_NUM 0x0A
#define MAX_BRIGHTNESS 8
diff --git a/arch/mips/loongson/lemote-2f/yeeloong_laptop/video_output.c
b/arch/mips/loongson/lemote-2f/yeeloong_laptop/video_output.c
new file mode 100644
index 0000000..e8b2f9a
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/yeeloong_laptop/video_output.c
@@ -0,0 +1,164 @@
+/*
+ * YeeLoong Video Output Driver
+ *
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/video_output.h>
+
+#include <asm/bootinfo.h>
+
+#include "ec_kb3310b.h"
+
+MODULE_AUTHOR("Wu Zhangjin <wuzj@lemote.com>");
+MODULE_DESCRIPTION("YeeLoong laptop video output driver");
+MODULE_LICENSE("GPL");
+
+static int lcd_video_output_get(struct output_device *od)
+{
+ return ec_read(REG_DISPLAY_LCD);
+}
+
+static int lcd_video_output_set(struct output_device *od)
+{
+ unsigned long status = od->request_state;
+ int value;
+
+ if (status == BIT_DISPLAY_LCD_ON) {
+ /* Turn on LCD */
+ outb(0x31, 0x3c4);
+ value = inb(0x3c5);
+ value = (value & 0xf8) | 0x03;
+ outb(0x31, 0x3c4);
+ outb(value, 0x3c5);
+ /* Turn on backlight */
+ ec_write(REG_BACKLIGHT_CTRL, BIT_BACKLIGHT_ON);
+ } else {
+ /* Turn off backlight */
+ ec_write(REG_BACKLIGHT_CTRL, BIT_BACKLIGHT_OFF);
+ /* Turn off LCD */
+ outb(0x31, 0x3c4);
+ value = inb(0x3c5);
+ value = (value & 0xf8) | 0x02;
+ outb(0x31, 0x3c4);
+ outb(value, 0x3c5);
+ }
+
+ return 0;
+}
+
+static struct output_properties lcd_output_properties = {
+ .set_state = lcd_video_output_set,
+ .get_status = lcd_video_output_get,
+};
+
+static int crt_video_output_get(struct output_device *od)
+{
+ return ec_read(REG_CRT_DETECT);
+}
+
+static int crt_video_output_set(struct output_device *od)
+{
+ unsigned long status = od->request_state;
+ int value;
+
+ if (status == BIT_CRT_DETECT_PLUG) {
+ if (ec_read(REG_CRT_DETECT) == BIT_CRT_DETECT_PLUG) {
+ /* Turn on CRT */
+ outb(0x21, 0x3c4);
+ value = inb(0x3c5);
+ value &= ~(1 << 7);
+ outb(0x21, 0x3c4);
+ outb(value, 0x3c5);
+ }
+ } else {
+ /* Turn off CRT */
+ outb(0x21, 0x3c4);
+ value = inb(0x3c5);
+ value |= (1 << 7);
+ outb(0x21, 0x3c4);
+ outb(value, 0x3c5);
+ }
+
+ return 0;
+}
+
+static struct output_properties crt_output_properties = {
+ .set_state = crt_video_output_set,
+ .get_status = crt_video_output_get,
+};
+
+struct output_device *lcd_output_dev, *crt_output_dev;
+
+void lcd_vo_set(int status)
+{
+ lcd_output_dev->request_state = status;
+ lcd_video_output_set(lcd_output_dev);
+}
+EXPORT_SYMBOL(lcd_vo_set);
+
+void crt_vo_set(int status)
+{
+ crt_output_dev->request_state = status;
+ crt_video_output_set(crt_output_dev);
+}
+EXPORT_SYMBOL(crt_vo_set);
+
+static int __init yeeloong_vo_init(void)
+{
+ int ret;
+
+ if (mips_machtype != MACH_LEMOTE_YL2F89) {
+ pr_err("This Driver is only for YeeLoong laptop\n");
+ return -EFAULT;
+ }
+
+
+ /* Register video output device: lcd, crt */
+ lcd_output_dev = video_output_register("LCD", NULL, NULL,
+ &lcd_output_properties);
+
+ if (IS_ERR(lcd_output_dev)) {
+ ret = PTR_ERR(lcd_output_dev);
+ lcd_output_dev = NULL;
+ return ret;
+ }
+ /* Ensure LCD is on by default */
+ lcd_vo_set(BIT_DISPLAY_LCD_ON);
+
+ crt_output_dev = video_output_register("CRT", NULL, NULL,
+ &crt_output_properties);
+
+ if (IS_ERR(crt_output_dev)) {
+ ret = PTR_ERR(crt_output_dev);
+ crt_output_dev = NULL;
+ return ret;
+ }
+
+ /* Turn off CRT by default, and will be enabled when the CRT
+ * connectting event reported by SCI */
+ crt_vo_set(BIT_CRT_DETECT_UNPLUG);
+
+ return 0;
+}
+
+static void __exit yeeloong_vo_exit(void)
+{
+ if (lcd_output_dev) {
+ video_output_unregister(lcd_output_dev);
+ lcd_output_dev = NULL;
+ }
+ if (crt_output_dev) {
+ video_output_unregister(crt_output_dev);
+ crt_output_dev = NULL;
+ }
+}
+
+module_init(yeeloong_vo_init);
+module_exit(yeeloong_vo_exit);
--
1.6.2.1
|