1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * |
4 | * LCD driver for HP Jornada 700 series (710/720/728) |
5 | * Copyright (C) 2006-2009 Kristoffer Ericson <kristoffer.ericson@gmail.com> |
6 | */ |
7 | |
8 | #include <linux/device.h> |
9 | #include <linux/fb.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/lcd.h> |
12 | #include <linux/module.h> |
13 | #include <linux/platform_device.h> |
14 | #include <linux/delay.h> |
15 | |
16 | #include <mach/jornada720.h> |
17 | #include <mach/hardware.h> |
18 | |
19 | #include <video/s1d13xxxfb.h> |
20 | |
21 | #define LCD_MAX_CONTRAST 0xff |
22 | #define LCD_DEF_CONTRAST 0x80 |
23 | |
24 | static int jornada_lcd_get_power(struct lcd_device *ld) |
25 | { |
26 | return PPSR & PPC_LDD2 ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; |
27 | } |
28 | |
29 | static int jornada_lcd_get_contrast(struct lcd_device *ld) |
30 | { |
31 | int ret; |
32 | |
33 | if (jornada_lcd_get_power(ld) != FB_BLANK_UNBLANK) |
34 | return 0; |
35 | |
36 | jornada_ssp_start(); |
37 | |
38 | if (jornada_ssp_byte(GETCONTRAST) == TXDUMMY) { |
39 | ret = jornada_ssp_byte(TXDUMMY); |
40 | goto success; |
41 | } |
42 | |
43 | dev_err(&ld->dev, "failed to set contrast\n" ); |
44 | ret = -ETIMEDOUT; |
45 | |
46 | success: |
47 | jornada_ssp_end(); |
48 | return ret; |
49 | } |
50 | |
51 | static int jornada_lcd_set_contrast(struct lcd_device *ld, int value) |
52 | { |
53 | int ret = 0; |
54 | |
55 | jornada_ssp_start(); |
56 | |
57 | /* start by sending our set contrast cmd to mcu */ |
58 | if (jornada_ssp_byte(SETCONTRAST) == TXDUMMY) { |
59 | /* if successful push the new value */ |
60 | if (jornada_ssp_byte(value) == TXDUMMY) |
61 | goto success; |
62 | } |
63 | |
64 | dev_err(&ld->dev, "failed to set contrast\n" ); |
65 | ret = -ETIMEDOUT; |
66 | |
67 | success: |
68 | jornada_ssp_end(); |
69 | return ret; |
70 | } |
71 | |
72 | static int jornada_lcd_set_power(struct lcd_device *ld, int power) |
73 | { |
74 | if (power != FB_BLANK_UNBLANK) { |
75 | PPSR &= ~PPC_LDD2; |
76 | PPDR |= PPC_LDD2; |
77 | } else { |
78 | PPSR |= PPC_LDD2; |
79 | } |
80 | |
81 | return 0; |
82 | } |
83 | |
84 | static struct lcd_ops jornada_lcd_props = { |
85 | .get_contrast = jornada_lcd_get_contrast, |
86 | .set_contrast = jornada_lcd_set_contrast, |
87 | .get_power = jornada_lcd_get_power, |
88 | .set_power = jornada_lcd_set_power, |
89 | }; |
90 | |
91 | static int jornada_lcd_probe(struct platform_device *pdev) |
92 | { |
93 | struct lcd_device *lcd_device; |
94 | int ret; |
95 | |
96 | lcd_device = devm_lcd_device_register(dev: &pdev->dev, S1D_DEVICENAME, |
97 | parent: &pdev->dev, NULL, ops: &jornada_lcd_props); |
98 | |
99 | if (IS_ERR(ptr: lcd_device)) { |
100 | ret = PTR_ERR(ptr: lcd_device); |
101 | dev_err(&pdev->dev, "failed to register device\n" ); |
102 | return ret; |
103 | } |
104 | |
105 | platform_set_drvdata(pdev, data: lcd_device); |
106 | |
107 | /* lets set our default values */ |
108 | jornada_lcd_set_contrast(ld: lcd_device, LCD_DEF_CONTRAST); |
109 | jornada_lcd_set_power(ld: lcd_device, power: FB_BLANK_UNBLANK); |
110 | /* give it some time to startup */ |
111 | msleep(msecs: 100); |
112 | |
113 | return 0; |
114 | } |
115 | |
116 | static struct platform_driver jornada_lcd_driver = { |
117 | .probe = jornada_lcd_probe, |
118 | .driver = { |
119 | .name = "jornada_lcd" , |
120 | }, |
121 | }; |
122 | |
123 | module_platform_driver(jornada_lcd_driver); |
124 | |
125 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>" ); |
126 | MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver" ); |
127 | MODULE_LICENSE("GPL" ); |
128 | |