1
/*
2
 *
3
 * LCD driver for HP Jornada 700 series (710/720/728)
4
 * Copyright (C) 2006-2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License version
8
 * 2 or any later version as published by the Free Software Foundation.
9
 *
10
 */
11
12
#include <linux/device.h>
13
#include <linux/fb.h>
14
#include <linux/kernel.h>
15
#include <linux/lcd.h>
16
#include <linux/module.h>
17
#include <linux/platform_device.h>
18
#include <linux/delay.h>
19
20
#include <mach/jornada720.h>
21
#include <mach/hardware.h>
22
23
#include <video/s1d13xxxfb.h>
24
25
#define LCD_MAX_CONTRAST	0xff
26
#define LCD_DEF_CONTRAST	0x80
27
28
static int jornada_lcd_get_power(struct lcd_device *dev)
29
{
30
	/* LDD2 in PPC = LCD POWER */
31
	if (PPSR & PPC_LDD2)
32
		return FB_BLANK_UNBLANK;	/* PW ON */
33
	else
34
		return FB_BLANK_POWERDOWN;	/* PW OFF */
35
}
36
37
static int jornada_lcd_get_contrast(struct lcd_device *dev)
38
{
39
	int ret;
40
41
	if (jornada_lcd_get_power(dev) != FB_BLANK_UNBLANK)
42
		return 0;
43
44
	jornada_ssp_start();
45
46
	if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) {
47
		printk(KERN_ERR "lcd: get contrast failed\n");
48
		jornada_ssp_end();
49
		return -ETIMEDOUT;
50
	} else {
51
		ret = jornada_ssp_byte(TXDUMMY);
52
		jornada_ssp_end();
53
		return ret;
54
	}
55
}
56
57
static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
58
{
59
	int ret;
60
61
	jornada_ssp_start();
62
63
	/* start by sending our set contrast cmd to mcu */
64
	ret = jornada_ssp_byte(SETCONTRAST);
65
66
	/* push the new value */
67
	if (jornada_ssp_byte(value) != TXDUMMY) {
68
		printk(KERN_ERR "lcd : set contrast failed\n");
69
		jornada_ssp_end();
70
		return -ETIMEDOUT;
71
	}
72
73
	/* if we get here we can assume everything went well */
74
	jornada_ssp_end();
75
76
	return 0;
77
}
78
79
static int jornada_lcd_set_power(struct lcd_device *dev, int power)
80
{
81
	if (power != FB_BLANK_UNBLANK) {
82
		PPSR &= ~PPC_LDD2;
83
		PPDR |= PPC_LDD2;
84
	} else
85
		PPSR |= PPC_LDD2;
86
87
	return 0;
88
}
89
90
static struct lcd_ops jornada_lcd_props = {
91
	.get_contrast = jornada_lcd_get_contrast,
92
	.set_contrast = jornada_lcd_set_contrast,
93
	.get_power = jornada_lcd_get_power,
94
	.set_power = jornada_lcd_set_power,
95
};
96
97
static int jornada_lcd_probe(struct platform_device *pdev)
98
{
99
	struct lcd_device *lcd_device;
100
	int ret;
101
102
	lcd_device = lcd_device_register(S1D_DEVICENAME, &pdev->dev, NULL, &jornada_lcd_props);
103
104
	if (IS_ERR(lcd_device)) {
105
		ret = PTR_ERR(lcd_device);
106
		printk(KERN_ERR "lcd : failed to register device\n");
107
		return ret;
108
	}
109
110
	platform_set_drvdata(pdev, lcd_device);
111
112
	/* lets set our default values */
113
	jornada_lcd_set_contrast(lcd_device, LCD_DEF_CONTRAST);
114
	jornada_lcd_set_power(lcd_device, FB_BLANK_UNBLANK);
115
	/* give it some time to startup */
116
	msleep(100);
117
118
	return 0;
119
}
120
121
static int jornada_lcd_remove(struct platform_device *pdev)
122
{
123
	struct lcd_device *lcd_device = platform_get_drvdata(pdev);
124
125
	lcd_device_unregister(lcd_device);
126
127
	return 0;
128
}
129
130
static struct platform_driver jornada_lcd_driver = {
131
	.probe	= jornada_lcd_probe,
132
	.remove	= jornada_lcd_remove,
133
	.driver	= {
134
		.name	= "jornada_lcd",
135
	},
136
};
137
138
int __init jornada_lcd_init(void)
139
{
140
	return platform_driver_register(&jornada_lcd_driver);
141
}
142
143
void __exit jornada_lcd_exit(void)
144
{
145
	platform_driver_unregister(&jornada_lcd_driver);
146
}
147
148
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
149
MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver");
150
MODULE_LICENSE("GPL");
151
152
module_init(jornada_lcd_init);
153
module_exit(jornada_lcd_exit);