Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
panel-sharp-ls037v7dw01.c
Go to the documentation of this file.
1 /*
2  * LCD panel driver for Sharp LS037V7DW01
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Author: Tomi Valkeinen <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 as published by
9  * the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <linux/module.h>
21 #include <linux/delay.h>
22 #include <linux/device.h>
23 #include <linux/backlight.h>
24 #include <linux/fb.h>
25 #include <linux/err.h>
26 #include <linux/slab.h>
27 
28 #include <video/omapdss.h>
29 
30 struct sharp_data {
32 };
33 
34 static struct omap_video_timings sharp_ls_timings = {
35  .x_res = 480,
36  .y_res = 640,
37 
38  .pixel_clock = 19200,
39 
40  .hsw = 2,
41  .hfp = 1,
42  .hbp = 28,
43 
44  .vsw = 1,
45  .vfp = 1,
46  .vbp = 1,
47 
48  .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
49  .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
50  .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
51  .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
52  .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
53 };
54 
55 static int sharp_ls_bl_update_status(struct backlight_device *bl)
56 {
57  struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
58  int level;
59 
60  if (!dssdev->set_backlight)
61  return -EINVAL;
62 
63  if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
64  bl->props.power == FB_BLANK_UNBLANK)
65  level = bl->props.brightness;
66  else
67  level = 0;
68 
69  return dssdev->set_backlight(dssdev, level);
70 }
71 
72 static int sharp_ls_bl_get_brightness(struct backlight_device *bl)
73 {
74  if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
75  bl->props.power == FB_BLANK_UNBLANK)
76  return bl->props.brightness;
77 
78  return 0;
79 }
80 
81 static const struct backlight_ops sharp_ls_bl_ops = {
82  .get_brightness = sharp_ls_bl_get_brightness,
83  .update_status = sharp_ls_bl_update_status,
84 };
85 
86 
87 
88 static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
89 {
90  struct backlight_properties props;
91  struct backlight_device *bl;
92  struct sharp_data *sd;
93  int r;
94 
95  dssdev->panel.timings = sharp_ls_timings;
96 
97  sd = kzalloc(sizeof(*sd), GFP_KERNEL);
98  if (!sd)
99  return -ENOMEM;
100 
101  dev_set_drvdata(&dssdev->dev, sd);
102 
103  memset(&props, 0, sizeof(struct backlight_properties));
104  props.max_brightness = dssdev->max_backlight_level;
105  props.type = BACKLIGHT_RAW;
106 
107  bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
108  &sharp_ls_bl_ops, &props);
109  if (IS_ERR(bl)) {
110  r = PTR_ERR(bl);
111  kfree(sd);
112  return r;
113  }
114  sd->bl = bl;
115 
116  bl->props.fb_blank = FB_BLANK_UNBLANK;
117  bl->props.power = FB_BLANK_UNBLANK;
118  bl->props.brightness = dssdev->max_backlight_level;
119  r = sharp_ls_bl_update_status(bl);
120  if (r < 0)
121  dev_err(&dssdev->dev, "failed to set lcd brightness\n");
122 
123  return 0;
124 }
125 
126 static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev)
127 {
128  struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
129  struct backlight_device *bl = sd->bl;
130 
131  bl->props.power = FB_BLANK_POWERDOWN;
132  sharp_ls_bl_update_status(bl);
134 
135  kfree(sd);
136 }
137 
138 static int sharp_ls_power_on(struct omap_dss_device *dssdev)
139 {
140  int r = 0;
141 
142  if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
143  return 0;
144 
145  omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
146  omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
147 
148  r = omapdss_dpi_display_enable(dssdev);
149  if (r)
150  goto err0;
151 
152  /* wait couple of vsyncs until enabling the LCD */
153  msleep(50);
154 
155  if (dssdev->platform_enable) {
156  r = dssdev->platform_enable(dssdev);
157  if (r)
158  goto err1;
159  }
160 
161  return 0;
162 err1:
164 err0:
165  return r;
166 }
167 
168 static void sharp_ls_power_off(struct omap_dss_device *dssdev)
169 {
170  if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
171  return;
172 
173  if (dssdev->platform_disable)
174  dssdev->platform_disable(dssdev);
175 
176  /* wait at least 5 vsyncs after disabling the LCD */
177 
178  msleep(100);
179 
181 }
182 
183 static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
184 {
185  int r;
186  r = sharp_ls_power_on(dssdev);
187  dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
188  return r;
189 }
190 
191 static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
192 {
193  sharp_ls_power_off(dssdev);
195 }
196 
197 static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
198 {
199  sharp_ls_power_off(dssdev);
201  return 0;
202 }
203 
204 static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
205 {
206  int r;
207  r = sharp_ls_power_on(dssdev);
208  dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
209  return r;
210 }
211 
212 static struct omap_dss_driver sharp_ls_driver = {
213  .probe = sharp_ls_panel_probe,
214  .remove = __exit_p(sharp_ls_panel_remove),
215 
216  .enable = sharp_ls_panel_enable,
217  .disable = sharp_ls_panel_disable,
218  .suspend = sharp_ls_panel_suspend,
219  .resume = sharp_ls_panel_resume,
220 
221  .driver = {
222  .name = "sharp_ls_panel",
223  .owner = THIS_MODULE,
224  },
225 };
226 
227 static int __init sharp_ls_panel_drv_init(void)
228 {
229  return omap_dss_register_driver(&sharp_ls_driver);
230 }
231 
232 static void __exit sharp_ls_panel_drv_exit(void)
233 {
234  omap_dss_unregister_driver(&sharp_ls_driver);
235 }
236 
237 module_init(sharp_ls_panel_drv_init);
238 module_exit(sharp_ls_panel_drv_exit);
239 MODULE_LICENSE("GPL");