1 /*
2 * Copyright (C) 2013 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <linux/delay.h>
20 #include <linux/err.h>
21 #include <linux/i2c.h>
22 #include <linux/gpio.h>
23 #include <linux/of_gpio.h>
24 #include <linux/of_i2c.h>
25 #include <linux/of.h>
26 #include <linux/regmap.h>
28 #include <video/omapdss.h>
29 #include <video/omap-panel-tfcs9700.h>
31 #define TLC_NAME "tlc59108"
32 #define TLC_I2C_ADDR 0x40
34 #define TLC59108_MODE1 0x00
35 #define TLC59108_PWM2 0x04
36 #define TLC59108_LEDOUT0 0x0c
37 #define TLC59108_LEDOUT1 0x0d
39 struct tlc_data {
40 struct device *dev;
41 struct regmap *regmap;
42 int p_gpio;
43 };
45 static const struct omap_video_timings tfc_s9700_default_timings = {
46 .x_res = 800,
47 .y_res = 480,
49 .pixel_clock = 29232,
51 .hfp = 41,
52 .hsw = 49,
53 .hbp = 41,
55 .vfp = 13,
56 .vsw = 4,
57 .vbp = 29,
59 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
60 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
61 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
62 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
63 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
64 };
66 struct panel_drv_data {
67 struct omap_dss_device *dssdev;
69 struct i2c_client *tlc_client;
70 struct mutex lock;
72 int dith;
73 };
75 static int tlc_init(struct i2c_client *client)
76 {
77 struct tlc_data *data = dev_get_drvdata(&client->dev);
78 struct regmap *map = data->regmap;
80 /* init the TLC chip */
81 regmap_write(map, TLC59108_MODE1, 0x01);
83 /*
84 * set LED1(AVDD) to ON state(default), enable LED2 in PWM mode, enable
85 * LED0 to OFF state
86 */
87 regmap_write(map, TLC59108_LEDOUT0, 0x21);
89 /* set LED2 PWM to full freq */
90 regmap_write(map, TLC59108_PWM2, 0xff);
92 /* set LED4(UPDN) and LED6(MODE3) to OFF state */
93 regmap_write(map, TLC59108_LEDOUT1, 0x11);
95 return 0;
96 }
98 static int tlc_uninit(struct i2c_client *client)
99 {
100 struct tlc_data *data = dev_get_drvdata(&client->dev);
101 struct regmap *map = data->regmap;
103 /* clear TLC chip regs */
104 regmap_write(map, TLC59108_PWM2, 0x0);
105 regmap_write(map, TLC59108_LEDOUT0, 0x0);
106 regmap_write(map, TLC59108_LEDOUT1, 0x0);
108 regmap_write(map, TLC59108_MODE1, 0x0);
110 return 0;
111 }
113 static int tfc_s9700_power_on(struct omap_dss_device *dssdev)
114 {
115 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
116 int r;
118 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
119 return 0;
121 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
122 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
124 r = omapdss_dpi_display_enable(dssdev);
125 if (r)
126 goto err0;
128 tlc_init(ddata->tlc_client);
130 return 0;
131 err0:
132 return r;
133 }
135 static void tfc_s9700_power_off(struct omap_dss_device *dssdev)
136 {
137 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
139 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
140 return;
142 tlc_uninit(ddata->tlc_client);
144 omapdss_dpi_display_disable(dssdev);
145 }
147 static int tfc_s9700_probe_of(struct omap_dss_device *dssdev,
148 struct panel_drv_data *ddata)
149 {
150 struct device_node *node = dssdev->dev.of_node;
151 struct device_node *tlc;
152 struct i2c_client *client;
153 int r, datalines;
155 r = of_property_read_u32(node, "data-lines", &datalines);
156 if (r) {
157 dev_err(&dssdev->dev, "failed to parse datalines");
158 return r;
159 }
161 tlc = of_parse_phandle(node, "tlc", 0);
162 if (!tlc) {
163 dev_err(&dssdev->dev, "could not find tlc device\n");
164 return -EINVAL;
165 }
167 client = of_find_i2c_device_by_node(tlc);
168 if (!client) {
169 dev_err(&dssdev->dev, "failed to find tlc i2c client device\n");
170 return -EINVAL;
171 }
173 ddata->tlc_client = client;
175 dssdev->phy.dpi.data_lines = datalines;
177 return 0;
178 }
180 static struct i2c_board_info tlc_i2c_board_info = {
181 I2C_BOARD_INFO(TLC_NAME, TLC_I2C_ADDR),
182 };
184 static int tfc_s9700_probe(struct omap_dss_device *dssdev)
185 {
186 struct panel_drv_data *ddata;
187 int r;
189 ddata = devm_kzalloc(&dssdev->dev, sizeof(*ddata), GFP_KERNEL);
190 if (!ddata)
191 return -ENOMEM;
193 dssdev->panel.timings = tfc_s9700_default_timings;
195 ddata->dssdev = dssdev;
196 mutex_init(&ddata->lock);
198 if (dssdev->dev.of_node) {
199 r = tfc_s9700_probe_of(dssdev, ddata);
200 if (r)
201 return r;
202 } else if (dssdev->data) {
203 struct tfc_s9700_platform_data *pdata = dssdev->data;
204 struct i2c_client *client;
205 struct i2c_adapter *adapter;
206 int tlc_adapter_id;
208 dssdev->phy.dpi.data_lines = pdata->datalines;
210 tlc_adapter_id = pdata->tlc_adapter_id;
212 adapter = i2c_get_adapter(tlc_adapter_id);
213 if (!adapter) {
214 dev_err(&dssdev->dev, "can't get i2c adapter\n");
215 return -ENODEV;
216 }
218 client = i2c_new_device(adapter, &tlc_i2c_board_info);
219 if (!client) {
220 dev_err(&dssdev->dev, "can't add i2c device\n");
221 return -ENODEV;
222 }
224 ddata->tlc_client = client;
225 } else {
226 return -EINVAL;
227 }
230 if (dssdev->phy.dpi.data_lines == 24)
231 ddata->dith = 0;
232 else if (dssdev->phy.dpi.data_lines == 18)
233 ddata->dith = 1;
234 else
235 return -EINVAL;
237 dev_set_drvdata(&dssdev->dev, ddata);
239 return 0;
240 }
242 static void __exit tfc_s9700_remove(struct omap_dss_device *dssdev)
243 {
244 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
246 mutex_lock(&ddata->lock);
248 dev_set_drvdata(&dssdev->dev, NULL);
250 mutex_unlock(&ddata->lock);
251 }
253 static int tfc_s9700_enable(struct omap_dss_device *dssdev)
254 {
255 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
256 int r;
258 mutex_lock(&ddata->lock);
260 r = tfc_s9700_power_on(dssdev);
261 if (r == 0)
262 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
264 mutex_unlock(&ddata->lock);
266 return r;
267 }
269 static void tfc_s9700_disable(struct omap_dss_device *dssdev)
270 {
271 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
273 mutex_lock(&ddata->lock);
275 tfc_s9700_power_off(dssdev);
277 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
279 mutex_unlock(&ddata->lock);
280 }
282 static void tfc_s9700_set_timings(struct omap_dss_device *dssdev,
283 struct omap_video_timings *timings)
284 {
285 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
287 mutex_lock(&ddata->lock);
288 omapdss_dpi_set_timings(dssdev, timings);
289 dssdev->panel.timings = *timings;
290 mutex_unlock(&ddata->lock);
291 }
293 static void tfc_s9700_get_timings(struct omap_dss_device *dssdev,
294 struct omap_video_timings *timings)
295 {
296 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
298 mutex_lock(&ddata->lock);
299 *timings = dssdev->panel.timings;
300 mutex_unlock(&ddata->lock);
301 }
303 static int tfc_s9700_check_timings(struct omap_dss_device *dssdev,
304 struct omap_video_timings *timings)
305 {
306 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
307 int r;
309 mutex_lock(&ddata->lock);
310 r = dpi_check_timings(dssdev, timings);
311 mutex_unlock(&ddata->lock);
313 return r;
314 }
316 #if defined(CONFIG_OF)
317 static const struct of_device_id tfc_s9700_of_match[] = {
318 {
319 .compatible = "ti,tfc_s9700",
320 },
321 {},
322 };
324 MODULE_DEVICE_TABLE(of, tfc_s9700_of_match);
325 #else
326 #define dss_of_match NULL
327 #endif
329 static struct omap_dss_driver tfc_s9700_driver = {
330 .probe = tfc_s9700_probe,
331 .remove = __exit_p(tfc_s9700_remove),
333 .enable = tfc_s9700_enable,
334 .disable = tfc_s9700_disable,
336 .set_timings = tfc_s9700_set_timings,
337 .get_timings = tfc_s9700_get_timings,
338 .check_timings = tfc_s9700_check_timings,
340 .driver = {
341 .name = "tfc_s9700",
342 .owner = THIS_MODULE,
343 .of_match_table = tfc_s9700_of_match,
344 },
345 };
347 struct regmap_config tlc59108_regmap_config = {
348 .reg_bits = 8,
349 .val_bits = 8,
350 };
352 static int tlc59108_i2c_probe(struct i2c_client *client,
353 const struct i2c_device_id *id)
354 {
355 int r;
356 struct regmap *regmap;
357 struct tlc_data *data;
358 struct device *dev = &client->dev;
359 struct device_node *node = dev->of_node;
360 unsigned int val;
361 int gpio;
363 regmap = devm_regmap_init_i2c(client, &tlc59108_regmap_config);
364 if (IS_ERR(regmap)) {
365 r = PTR_ERR(regmap);
366 dev_err(&client->dev, "Failed to init regmap: %d\n", r);
367 return r;
368 }
370 data = devm_kzalloc(dev, sizeof(struct tlc_data), GFP_KERNEL);
371 if (!data)
372 return -ENOMEM;
374 gpio = of_get_gpio(node, 0);
376 if (gpio_is_valid(gpio)) {
377 data->p_gpio = gpio;
378 } else if (gpio == -ENOENT) {
379 data->p_gpio = -1;
380 } else {
381 dev_err(dev, "failed to parse Power gpio\n");
382 return gpio;
383 }
385 if (gpio_is_valid(data->p_gpio)) {
386 r = devm_gpio_request_one(dev, data->p_gpio, GPIOF_OUT_INIT_LOW,
387 "tfc_s9700 p_gpio");
388 if (r) {
389 dev_err(dev, "Failed to request Power GPIO %d\n",
390 data->p_gpio);
391 return r;
392 }
393 }
395 dev_set_drvdata(dev, data);
396 data->dev = dev;
397 data->regmap = regmap;
399 msleep(10);
401 /* Try to read a TLC register to verify if i2c works */
402 r = regmap_read(data->regmap, TLC59108_MODE1, &val);
403 if (r < 0) {
404 dev_err(dev, "Failed to set MODE1: %d\n", r);
405 return r;
406 }
408 dev_info(dev, "Successfully initialized %s\n", TLC_NAME);
410 return 0;
411 }
413 static int tlc59108_i2c_remove(struct i2c_client *client)
414 {
415 struct tlc_data *data = dev_get_drvdata(&client->dev);
417 if (gpio_is_valid(data->p_gpio))
418 gpio_set_value_cansleep(data->p_gpio, 1);
420 return 0;
421 }
423 static const struct i2c_device_id tlc59108_id[] = {
424 { TLC_NAME, 0 },
425 { }
426 };
427 MODULE_DEVICE_TABLE(i2c, tlc59108_id);
429 static const struct of_device_id tlc59108_of_match[] = {
430 { .compatible = "ti,tlc59108", },
431 { },
432 };
433 MODULE_DEVICE_TABLE(of, tlc59108_of_match);
435 static struct i2c_driver tlc59108_i2c_driver = {
436 .driver = {
437 .owner = THIS_MODULE,
438 .name = TLC_NAME,
439 .of_match_table = tlc59108_of_match,
440 },
441 .id_table = tlc59108_id,
442 .probe = tlc59108_i2c_probe,
443 .remove = tlc59108_i2c_remove,
444 };
446 static int __init tfc_s9700_init(void)
447 {
448 int r;
450 r = i2c_add_driver(&tlc59108_i2c_driver);
451 if (r) {
452 printk(KERN_WARNING "tlc59108 driver" \
453 " registration failed\n");
454 return r;
455 }
457 r = omap_dss_register_driver(&tfc_s9700_driver);
458 if (r)
459 i2c_del_driver(&tlc59108_i2c_driver);
461 return r;
462 }
464 static void __exit tfc_s9700_exit(void)
465 {
466 omap_dss_unregister_driver(&tfc_s9700_driver);
467 }
469 module_init(tfc_s9700_init);
470 module_exit(tfc_s9700_exit);
471 MODULE_LICENSE("GPL");