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 struct device *i2c_dev;
188 int r;
190 ddata = devm_kzalloc(&dssdev->dev, sizeof(*ddata), GFP_KERNEL);
191 if (!ddata)
192 return -ENOMEM;
194 dssdev->panel.timings = tfc_s9700_default_timings;
196 ddata->dssdev = dssdev;
197 mutex_init(&ddata->lock);
199 if (dssdev->dev.of_node) {
200 r = tfc_s9700_probe_of(dssdev, ddata);
201 if (r)
202 return r;
203 } else if (dssdev->data) {
204 struct tfc_s9700_platform_data *pdata = dssdev->data;
205 struct i2c_client *client;
206 struct i2c_adapter *adapter;
207 int tlc_adapter_id;
209 dssdev->phy.dpi.data_lines = pdata->datalines;
211 tlc_adapter_id = pdata->tlc_adapter_id;
213 adapter = i2c_get_adapter(tlc_adapter_id);
214 if (!adapter) {
215 dev_err(&dssdev->dev, "can't get i2c adapter\n");
216 return -ENODEV;
217 }
219 client = i2c_new_device(adapter, &tlc_i2c_board_info);
220 if (!client) {
221 dev_err(&dssdev->dev, "can't add i2c device\n");
222 return -ENODEV;
223 }
225 ddata->tlc_client = client;
226 } else {
227 return -EINVAL;
228 }
230 i2c_dev = &ddata->tlc_client->dev;
231 if (!i2c_dev->driver) {
232 dev_err(&dssdev->dev, "tlc i2c client has no driver\n");
233 return -EINVAL;
234 }
236 if (dssdev->phy.dpi.data_lines == 24)
237 ddata->dith = 0;
238 else if (dssdev->phy.dpi.data_lines == 18)
239 ddata->dith = 1;
240 else
241 return -EINVAL;
243 dev_set_drvdata(&dssdev->dev, ddata);
245 return 0;
246 }
248 static void __exit tfc_s9700_remove(struct omap_dss_device *dssdev)
249 {
250 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
252 mutex_lock(&ddata->lock);
254 dev_set_drvdata(&dssdev->dev, NULL);
256 mutex_unlock(&ddata->lock);
257 }
259 static int tfc_s9700_enable(struct omap_dss_device *dssdev)
260 {
261 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
262 int r;
264 mutex_lock(&ddata->lock);
266 r = tfc_s9700_power_on(dssdev);
267 if (r == 0)
268 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
270 mutex_unlock(&ddata->lock);
272 return r;
273 }
275 static void tfc_s9700_disable(struct omap_dss_device *dssdev)
276 {
277 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
279 mutex_lock(&ddata->lock);
281 tfc_s9700_power_off(dssdev);
283 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
285 mutex_unlock(&ddata->lock);
286 }
288 static void tfc_s9700_set_timings(struct omap_dss_device *dssdev,
289 struct omap_video_timings *timings)
290 {
291 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
293 mutex_lock(&ddata->lock);
294 omapdss_dpi_set_timings(dssdev, timings);
295 dssdev->panel.timings = *timings;
296 mutex_unlock(&ddata->lock);
297 }
299 static void tfc_s9700_get_timings(struct omap_dss_device *dssdev,
300 struct omap_video_timings *timings)
301 {
302 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
304 mutex_lock(&ddata->lock);
305 *timings = dssdev->panel.timings;
306 mutex_unlock(&ddata->lock);
307 }
309 static int tfc_s9700_check_timings(struct omap_dss_device *dssdev,
310 struct omap_video_timings *timings)
311 {
312 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
313 int r;
315 mutex_lock(&ddata->lock);
316 r = dpi_check_timings(dssdev, timings);
317 mutex_unlock(&ddata->lock);
319 return r;
320 }
322 #if defined(CONFIG_OF)
323 static const struct of_device_id tfc_s9700_of_match[] = {
324 {
325 .compatible = "ti,tfc_s9700",
326 },
327 {},
328 };
330 MODULE_DEVICE_TABLE(of, tfc_s9700_of_match);
331 #else
332 #define dss_of_match NULL
333 #endif
335 static struct omap_dss_driver tfc_s9700_driver = {
336 .probe = tfc_s9700_probe,
337 .remove = __exit_p(tfc_s9700_remove),
339 .enable = tfc_s9700_enable,
340 .disable = tfc_s9700_disable,
342 .set_timings = tfc_s9700_set_timings,
343 .get_timings = tfc_s9700_get_timings,
344 .check_timings = tfc_s9700_check_timings,
346 .driver = {
347 .name = "tfc_s9700",
348 .owner = THIS_MODULE,
349 .of_match_table = tfc_s9700_of_match,
350 },
351 };
353 struct regmap_config tlc59108_regmap_config = {
354 .reg_bits = 8,
355 .val_bits = 8,
356 };
358 static int tlc59108_i2c_probe(struct i2c_client *client,
359 const struct i2c_device_id *id)
360 {
361 int r;
362 struct regmap *regmap;
363 struct tlc_data *data;
364 struct device *dev = &client->dev;
365 struct device_node *node = dev->of_node;
366 unsigned int val;
367 int gpio;
369 regmap = devm_regmap_init_i2c(client, &tlc59108_regmap_config);
370 if (IS_ERR(regmap)) {
371 r = PTR_ERR(regmap);
372 dev_err(&client->dev, "Failed to init regmap: %d\n", r);
373 return r;
374 }
376 data = devm_kzalloc(dev, sizeof(struct tlc_data), GFP_KERNEL);
377 if (!data)
378 return -ENOMEM;
380 gpio = of_get_gpio(node, 0);
382 if (gpio_is_valid(gpio)) {
383 data->p_gpio = gpio;
384 } else if (gpio == -ENOENT) {
385 data->p_gpio = -1;
386 } else {
387 dev_err(dev, "failed to parse Power gpio\n");
388 return gpio;
389 }
391 if (gpio_is_valid(data->p_gpio)) {
392 r = devm_gpio_request_one(dev, data->p_gpio, GPIOF_OUT_INIT_LOW,
393 "tfc_s9700 p_gpio");
394 if (r) {
395 dev_err(dev, "Failed to request Power GPIO %d\n",
396 data->p_gpio);
397 return r;
398 }
399 }
401 dev_set_drvdata(dev, data);
402 data->dev = dev;
403 data->regmap = regmap;
405 msleep(10);
407 /* Try to read a TLC register to verify if i2c works */
408 r = regmap_read(data->regmap, TLC59108_MODE1, &val);
409 if (r < 0) {
410 dev_err(dev, "Failed to set MODE1: %d\n", r);
411 return r;
412 }
414 dev_info(dev, "Successfully initialized %s\n", TLC_NAME);
416 return 0;
417 }
419 static int tlc59108_i2c_remove(struct i2c_client *client)
420 {
421 struct tlc_data *data = dev_get_drvdata(&client->dev);
423 if (gpio_is_valid(data->p_gpio))
424 gpio_set_value_cansleep(data->p_gpio, 1);
426 return 0;
427 }
429 static const struct i2c_device_id tlc59108_id[] = {
430 { TLC_NAME, 0 },
431 { }
432 };
433 MODULE_DEVICE_TABLE(i2c, tlc59108_id);
435 static const struct of_device_id tlc59108_of_match[] = {
436 { .compatible = "ti,tlc59108", },
437 { },
438 };
439 MODULE_DEVICE_TABLE(of, tlc59108_of_match);
441 static struct i2c_driver tlc59108_i2c_driver = {
442 .driver = {
443 .owner = THIS_MODULE,
444 .name = TLC_NAME,
445 .of_match_table = tlc59108_of_match,
446 },
447 .id_table = tlc59108_id,
448 .probe = tlc59108_i2c_probe,
449 .remove = tlc59108_i2c_remove,
450 };
452 static int __init tfc_s9700_init(void)
453 {
454 int r;
456 r = i2c_add_driver(&tlc59108_i2c_driver);
457 if (r) {
458 printk(KERN_WARNING "tlc59108 driver" \
459 " registration failed\n");
460 return r;
461 }
463 r = omap_dss_register_driver(&tfc_s9700_driver);
464 if (r)
465 i2c_del_driver(&tlc59108_i2c_driver);
467 return r;
468 }
470 static void __exit tfc_s9700_exit(void)
471 {
472 omap_dss_unregister_driver(&tfc_s9700_driver);
473 }
475 module_init(tfc_s9700_init);
476 module_exit(tfc_s9700_exit);
477 MODULE_LICENSE("GPL");