12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21be9ca25SJingoo Han /*
31be9ca25SJingoo Han * lms501kf03 TFT LCD panel driver.
41be9ca25SJingoo Han *
51be9ca25SJingoo Han * Copyright (c) 2012 Samsung Electronics Co., Ltd.
61be9ca25SJingoo Han * Author: Jingoo Han <jg1.han@samsung.com>
71be9ca25SJingoo Han */
81be9ca25SJingoo Han
91be9ca25SJingoo Han #include <linux/backlight.h>
101be9ca25SJingoo Han #include <linux/delay.h>
111be9ca25SJingoo Han #include <linux/fb.h>
121be9ca25SJingoo Han #include <linux/lcd.h>
131be9ca25SJingoo Han #include <linux/module.h>
141be9ca25SJingoo Han #include <linux/spi/spi.h>
151be9ca25SJingoo Han #include <linux/wait.h>
161be9ca25SJingoo Han
171be9ca25SJingoo Han #define COMMAND_ONLY 0x00
181be9ca25SJingoo Han #define DATA_ONLY 0x01
191be9ca25SJingoo Han
201be9ca25SJingoo Han struct lms501kf03 {
211be9ca25SJingoo Han struct device *dev;
221be9ca25SJingoo Han struct spi_device *spi;
231be9ca25SJingoo Han unsigned int power;
241be9ca25SJingoo Han struct lcd_device *ld;
251be9ca25SJingoo Han struct lcd_platform_data *lcd_pd;
261be9ca25SJingoo Han };
271be9ca25SJingoo Han
281be9ca25SJingoo Han static const unsigned char seq_password[] = {
291be9ca25SJingoo Han 0xb9, 0xff, 0x83, 0x69,
301be9ca25SJingoo Han };
311be9ca25SJingoo Han
321be9ca25SJingoo Han static const unsigned char seq_power[] = {
331be9ca25SJingoo Han 0xb1, 0x01, 0x00, 0x34, 0x06, 0x00, 0x14, 0x14, 0x20, 0x28,
341be9ca25SJingoo Han 0x12, 0x12, 0x17, 0x0a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
351be9ca25SJingoo Han };
361be9ca25SJingoo Han
371be9ca25SJingoo Han static const unsigned char seq_display[] = {
381be9ca25SJingoo Han 0xb2, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00, 0xff, 0x00, 0x00,
391be9ca25SJingoo Han 0x00, 0x00, 0x03, 0x03, 0x00, 0x01,
401be9ca25SJingoo Han };
411be9ca25SJingoo Han
421be9ca25SJingoo Han static const unsigned char seq_rgb_if[] = {
431be9ca25SJingoo Han 0xb3, 0x09,
441be9ca25SJingoo Han };
451be9ca25SJingoo Han
461be9ca25SJingoo Han static const unsigned char seq_display_inv[] = {
471be9ca25SJingoo Han 0xb4, 0x01, 0x08, 0x77, 0x0e, 0x06,
481be9ca25SJingoo Han };
491be9ca25SJingoo Han
501be9ca25SJingoo Han static const unsigned char seq_vcom[] = {
511be9ca25SJingoo Han 0xb6, 0x4c, 0x2e,
521be9ca25SJingoo Han };
531be9ca25SJingoo Han
541be9ca25SJingoo Han static const unsigned char seq_gate[] = {
551be9ca25SJingoo Han 0xd5, 0x00, 0x05, 0x03, 0x29, 0x01, 0x07, 0x17, 0x68, 0x13,
561be9ca25SJingoo Han 0x37, 0x20, 0x31, 0x8a, 0x46, 0x9b, 0x57, 0x13, 0x02, 0x75,
571be9ca25SJingoo Han 0xb9, 0x64, 0xa8, 0x07, 0x0f, 0x04, 0x07,
581be9ca25SJingoo Han };
591be9ca25SJingoo Han
601be9ca25SJingoo Han static const unsigned char seq_panel[] = {
611be9ca25SJingoo Han 0xcc, 0x02,
621be9ca25SJingoo Han };
631be9ca25SJingoo Han
641be9ca25SJingoo Han static const unsigned char seq_col_mod[] = {
651be9ca25SJingoo Han 0x3a, 0x77,
661be9ca25SJingoo Han };
671be9ca25SJingoo Han
681be9ca25SJingoo Han static const unsigned char seq_w_gamma[] = {
691be9ca25SJingoo Han 0xe0, 0x00, 0x04, 0x09, 0x0f, 0x1f, 0x3f, 0x1f, 0x2f, 0x0a,
701be9ca25SJingoo Han 0x0f, 0x10, 0x16, 0x18, 0x16, 0x17, 0x0d, 0x15, 0x00, 0x04,
711be9ca25SJingoo Han 0x09, 0x0f, 0x38, 0x3f, 0x20, 0x39, 0x0a, 0x0f, 0x10, 0x16,
721be9ca25SJingoo Han 0x18, 0x16, 0x17, 0x0d, 0x15,
731be9ca25SJingoo Han };
741be9ca25SJingoo Han
751be9ca25SJingoo Han static const unsigned char seq_rgb_gamma[] = {
761be9ca25SJingoo Han 0xc1, 0x01, 0x03, 0x07, 0x0f, 0x1a, 0x22, 0x2c, 0x33, 0x3c,
771be9ca25SJingoo Han 0x46, 0x4f, 0x58, 0x60, 0x69, 0x71, 0x79, 0x82, 0x89, 0x92,
781be9ca25SJingoo Han 0x9a, 0xa1, 0xa9, 0xb1, 0xb9, 0xc1, 0xc9, 0xcf, 0xd6, 0xde,
791be9ca25SJingoo Han 0xe5, 0xec, 0xf3, 0xf9, 0xff, 0xdd, 0x39, 0x07, 0x1c, 0xcb,
801be9ca25SJingoo Han 0xab, 0x5f, 0x49, 0x80, 0x03, 0x07, 0x0f, 0x19, 0x20, 0x2a,
811be9ca25SJingoo Han 0x31, 0x39, 0x42, 0x4b, 0x53, 0x5b, 0x63, 0x6b, 0x73, 0x7b,
821be9ca25SJingoo Han 0x83, 0x8a, 0x92, 0x9b, 0xa2, 0xaa, 0xb2, 0xba, 0xc2, 0xca,
831be9ca25SJingoo Han 0xd0, 0xd8, 0xe1, 0xe8, 0xf0, 0xf8, 0xff, 0xf7, 0xd8, 0xbe,
841be9ca25SJingoo Han 0xa7, 0x39, 0x40, 0x85, 0x8c, 0xc0, 0x04, 0x07, 0x0c, 0x17,
851be9ca25SJingoo Han 0x1c, 0x23, 0x2b, 0x34, 0x3b, 0x43, 0x4c, 0x54, 0x5b, 0x63,
861be9ca25SJingoo Han 0x6a, 0x73, 0x7a, 0x82, 0x8a, 0x91, 0x98, 0xa1, 0xa8, 0xb0,
871be9ca25SJingoo Han 0xb7, 0xc1, 0xc9, 0xcf, 0xd9, 0xe3, 0xea, 0xf4, 0xff, 0x00,
881be9ca25SJingoo Han 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
891be9ca25SJingoo Han };
901be9ca25SJingoo Han
911be9ca25SJingoo Han static const unsigned char seq_sleep_out[] = {
921be9ca25SJingoo Han 0x11,
931be9ca25SJingoo Han };
941be9ca25SJingoo Han
951be9ca25SJingoo Han static const unsigned char seq_display_on[] = {
961be9ca25SJingoo Han 0x29,
971be9ca25SJingoo Han };
981be9ca25SJingoo Han
991be9ca25SJingoo Han static const unsigned char seq_display_off[] = {
1001be9ca25SJingoo Han 0x10,
1011be9ca25SJingoo Han };
1021be9ca25SJingoo Han
lms501kf03_spi_write_byte(struct lms501kf03 * lcd,int addr,int data)1031be9ca25SJingoo Han static int lms501kf03_spi_write_byte(struct lms501kf03 *lcd, int addr, int data)
1041be9ca25SJingoo Han {
1051be9ca25SJingoo Han u16 buf[1];
1061be9ca25SJingoo Han struct spi_message msg;
1071be9ca25SJingoo Han
1081be9ca25SJingoo Han struct spi_transfer xfer = {
1091be9ca25SJingoo Han .len = 2,
1101be9ca25SJingoo Han .tx_buf = buf,
1111be9ca25SJingoo Han };
1121be9ca25SJingoo Han
1131be9ca25SJingoo Han buf[0] = (addr << 8) | data;
1141be9ca25SJingoo Han
1151be9ca25SJingoo Han spi_message_init(&msg);
1161be9ca25SJingoo Han spi_message_add_tail(&xfer, &msg);
1171be9ca25SJingoo Han
1181be9ca25SJingoo Han return spi_sync(lcd->spi, &msg);
1191be9ca25SJingoo Han }
1201be9ca25SJingoo Han
lms501kf03_spi_write(struct lms501kf03 * lcd,unsigned char address,unsigned char command)1211be9ca25SJingoo Han static int lms501kf03_spi_write(struct lms501kf03 *lcd, unsigned char address,
1221be9ca25SJingoo Han unsigned char command)
1231be9ca25SJingoo Han {
1241be9ca25SJingoo Han return lms501kf03_spi_write_byte(lcd, address, command);
1251be9ca25SJingoo Han }
1261be9ca25SJingoo Han
lms501kf03_panel_send_sequence(struct lms501kf03 * lcd,const unsigned char * wbuf,unsigned int len)1271be9ca25SJingoo Han static int lms501kf03_panel_send_sequence(struct lms501kf03 *lcd,
1281be9ca25SJingoo Han const unsigned char *wbuf,
1291be9ca25SJingoo Han unsigned int len)
1301be9ca25SJingoo Han {
1311be9ca25SJingoo Han int ret = 0, i = 0;
1321be9ca25SJingoo Han
1331be9ca25SJingoo Han while (i < len) {
1341be9ca25SJingoo Han if (i == 0)
1351be9ca25SJingoo Han ret = lms501kf03_spi_write(lcd, COMMAND_ONLY, wbuf[i]);
1361be9ca25SJingoo Han else
1371be9ca25SJingoo Han ret = lms501kf03_spi_write(lcd, DATA_ONLY, wbuf[i]);
1381be9ca25SJingoo Han if (ret)
1391be9ca25SJingoo Han break;
1401be9ca25SJingoo Han i += 1;
1411be9ca25SJingoo Han }
1421be9ca25SJingoo Han
1431be9ca25SJingoo Han return ret;
1441be9ca25SJingoo Han }
1451be9ca25SJingoo Han
lms501kf03_ldi_init(struct lms501kf03 * lcd)1461be9ca25SJingoo Han static int lms501kf03_ldi_init(struct lms501kf03 *lcd)
1471be9ca25SJingoo Han {
1481be9ca25SJingoo Han int ret, i;
1491be9ca25SJingoo Han static const unsigned char *init_seq[] = {
1501be9ca25SJingoo Han seq_password,
1511be9ca25SJingoo Han seq_power,
1521be9ca25SJingoo Han seq_display,
1531be9ca25SJingoo Han seq_rgb_if,
1541be9ca25SJingoo Han seq_display_inv,
1551be9ca25SJingoo Han seq_vcom,
1561be9ca25SJingoo Han seq_gate,
1571be9ca25SJingoo Han seq_panel,
1581be9ca25SJingoo Han seq_col_mod,
1591be9ca25SJingoo Han seq_w_gamma,
1601be9ca25SJingoo Han seq_rgb_gamma,
1611be9ca25SJingoo Han seq_sleep_out,
1621be9ca25SJingoo Han };
1631be9ca25SJingoo Han
1641be9ca25SJingoo Han static const unsigned int size_seq[] = {
1651be9ca25SJingoo Han ARRAY_SIZE(seq_password),
1661be9ca25SJingoo Han ARRAY_SIZE(seq_power),
1671be9ca25SJingoo Han ARRAY_SIZE(seq_display),
1681be9ca25SJingoo Han ARRAY_SIZE(seq_rgb_if),
1691be9ca25SJingoo Han ARRAY_SIZE(seq_display_inv),
1701be9ca25SJingoo Han ARRAY_SIZE(seq_vcom),
1711be9ca25SJingoo Han ARRAY_SIZE(seq_gate),
1721be9ca25SJingoo Han ARRAY_SIZE(seq_panel),
1731be9ca25SJingoo Han ARRAY_SIZE(seq_col_mod),
1741be9ca25SJingoo Han ARRAY_SIZE(seq_w_gamma),
1751be9ca25SJingoo Han ARRAY_SIZE(seq_rgb_gamma),
1761be9ca25SJingoo Han ARRAY_SIZE(seq_sleep_out),
1771be9ca25SJingoo Han };
1781be9ca25SJingoo Han
1791be9ca25SJingoo Han for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
1801be9ca25SJingoo Han ret = lms501kf03_panel_send_sequence(lcd, init_seq[i],
1811be9ca25SJingoo Han size_seq[i]);
1821be9ca25SJingoo Han if (ret)
1831be9ca25SJingoo Han break;
1841be9ca25SJingoo Han }
1851be9ca25SJingoo Han /*
1861be9ca25SJingoo Han * According to the datasheet, 120ms delay time is required.
1871be9ca25SJingoo Han * After sleep out sequence, command is blocked for 120ms.
1881be9ca25SJingoo Han * Thus, LDI should wait for 120ms.
1891be9ca25SJingoo Han */
1901be9ca25SJingoo Han msleep(120);
1911be9ca25SJingoo Han
1921be9ca25SJingoo Han return ret;
1931be9ca25SJingoo Han }
1941be9ca25SJingoo Han
lms501kf03_ldi_enable(struct lms501kf03 * lcd)1951be9ca25SJingoo Han static int lms501kf03_ldi_enable(struct lms501kf03 *lcd)
1961be9ca25SJingoo Han {
1971be9ca25SJingoo Han return lms501kf03_panel_send_sequence(lcd, seq_display_on,
1981be9ca25SJingoo Han ARRAY_SIZE(seq_display_on));
1991be9ca25SJingoo Han }
2001be9ca25SJingoo Han
lms501kf03_ldi_disable(struct lms501kf03 * lcd)2011be9ca25SJingoo Han static int lms501kf03_ldi_disable(struct lms501kf03 *lcd)
2021be9ca25SJingoo Han {
2031be9ca25SJingoo Han return lms501kf03_panel_send_sequence(lcd, seq_display_off,
2041be9ca25SJingoo Han ARRAY_SIZE(seq_display_off));
2051be9ca25SJingoo Han }
2061be9ca25SJingoo Han
lms501kf03_power_is_on(int power)2071be9ca25SJingoo Han static int lms501kf03_power_is_on(int power)
2081be9ca25SJingoo Han {
2091be9ca25SJingoo Han return (power) <= FB_BLANK_NORMAL;
2101be9ca25SJingoo Han }
2111be9ca25SJingoo Han
lms501kf03_power_on(struct lms501kf03 * lcd)2121be9ca25SJingoo Han static int lms501kf03_power_on(struct lms501kf03 *lcd)
2131be9ca25SJingoo Han {
2141be9ca25SJingoo Han int ret = 0;
2151be9ca25SJingoo Han struct lcd_platform_data *pd;
2161be9ca25SJingoo Han
2171be9ca25SJingoo Han pd = lcd->lcd_pd;
2181be9ca25SJingoo Han
2191be9ca25SJingoo Han if (!pd->power_on) {
2201be9ca25SJingoo Han dev_err(lcd->dev, "power_on is NULL.\n");
2211be9ca25SJingoo Han return -EINVAL;
222b50ffb8aSJingoo Han }
223b50ffb8aSJingoo Han
2241be9ca25SJingoo Han pd->power_on(lcd->ld, 1);
2251be9ca25SJingoo Han msleep(pd->power_on_delay);
2261be9ca25SJingoo Han
2271be9ca25SJingoo Han if (!pd->reset) {
2281be9ca25SJingoo Han dev_err(lcd->dev, "reset is NULL.\n");
2291be9ca25SJingoo Han return -EINVAL;
230b50ffb8aSJingoo Han }
231b50ffb8aSJingoo Han
2321be9ca25SJingoo Han pd->reset(lcd->ld);
2331be9ca25SJingoo Han msleep(pd->reset_delay);
2341be9ca25SJingoo Han
2351be9ca25SJingoo Han ret = lms501kf03_ldi_init(lcd);
2361be9ca25SJingoo Han if (ret) {
2371be9ca25SJingoo Han dev_err(lcd->dev, "failed to initialize ldi.\n");
2381be9ca25SJingoo Han return ret;
2391be9ca25SJingoo Han }
2401be9ca25SJingoo Han
2411be9ca25SJingoo Han ret = lms501kf03_ldi_enable(lcd);
2421be9ca25SJingoo Han if (ret) {
2431be9ca25SJingoo Han dev_err(lcd->dev, "failed to enable ldi.\n");
2441be9ca25SJingoo Han return ret;
2451be9ca25SJingoo Han }
2461be9ca25SJingoo Han
2471be9ca25SJingoo Han return 0;
2481be9ca25SJingoo Han }
2491be9ca25SJingoo Han
lms501kf03_power_off(struct lms501kf03 * lcd)2501be9ca25SJingoo Han static int lms501kf03_power_off(struct lms501kf03 *lcd)
2511be9ca25SJingoo Han {
2521be9ca25SJingoo Han int ret = 0;
2531be9ca25SJingoo Han struct lcd_platform_data *pd;
2541be9ca25SJingoo Han
2551be9ca25SJingoo Han pd = lcd->lcd_pd;
2561be9ca25SJingoo Han
2571be9ca25SJingoo Han ret = lms501kf03_ldi_disable(lcd);
2581be9ca25SJingoo Han if (ret) {
2591be9ca25SJingoo Han dev_err(lcd->dev, "lcd setting failed.\n");
2601be9ca25SJingoo Han return -EIO;
2611be9ca25SJingoo Han }
2621be9ca25SJingoo Han
2631be9ca25SJingoo Han msleep(pd->power_off_delay);
2641be9ca25SJingoo Han
2651be9ca25SJingoo Han pd->power_on(lcd->ld, 0);
2661be9ca25SJingoo Han
2671be9ca25SJingoo Han return 0;
2681be9ca25SJingoo Han }
2691be9ca25SJingoo Han
lms501kf03_power(struct lms501kf03 * lcd,int power)2701be9ca25SJingoo Han static int lms501kf03_power(struct lms501kf03 *lcd, int power)
2711be9ca25SJingoo Han {
2721be9ca25SJingoo Han int ret = 0;
2731be9ca25SJingoo Han
2741be9ca25SJingoo Han if (lms501kf03_power_is_on(power) &&
2751be9ca25SJingoo Han !lms501kf03_power_is_on(lcd->power))
2761be9ca25SJingoo Han ret = lms501kf03_power_on(lcd);
2771be9ca25SJingoo Han else if (!lms501kf03_power_is_on(power) &&
2781be9ca25SJingoo Han lms501kf03_power_is_on(lcd->power))
2791be9ca25SJingoo Han ret = lms501kf03_power_off(lcd);
2801be9ca25SJingoo Han
2811be9ca25SJingoo Han if (!ret)
2821be9ca25SJingoo Han lcd->power = power;
2831be9ca25SJingoo Han
2841be9ca25SJingoo Han return ret;
2851be9ca25SJingoo Han }
2861be9ca25SJingoo Han
lms501kf03_get_power(struct lcd_device * ld)2871be9ca25SJingoo Han static int lms501kf03_get_power(struct lcd_device *ld)
2881be9ca25SJingoo Han {
2891be9ca25SJingoo Han struct lms501kf03 *lcd = lcd_get_data(ld);
2901be9ca25SJingoo Han
2911be9ca25SJingoo Han return lcd->power;
2921be9ca25SJingoo Han }
2931be9ca25SJingoo Han
lms501kf03_set_power(struct lcd_device * ld,int power)2941be9ca25SJingoo Han static int lms501kf03_set_power(struct lcd_device *ld, int power)
2951be9ca25SJingoo Han {
2961be9ca25SJingoo Han struct lms501kf03 *lcd = lcd_get_data(ld);
2971be9ca25SJingoo Han
2981be9ca25SJingoo Han if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
2991be9ca25SJingoo Han power != FB_BLANK_NORMAL) {
3001be9ca25SJingoo Han dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
3011be9ca25SJingoo Han return -EINVAL;
3021be9ca25SJingoo Han }
3031be9ca25SJingoo Han
3041be9ca25SJingoo Han return lms501kf03_power(lcd, power);
3051be9ca25SJingoo Han }
3061be9ca25SJingoo Han
3071be9ca25SJingoo Han static struct lcd_ops lms501kf03_lcd_ops = {
3081be9ca25SJingoo Han .get_power = lms501kf03_get_power,
3091be9ca25SJingoo Han .set_power = lms501kf03_set_power,
3101be9ca25SJingoo Han };
3111be9ca25SJingoo Han
lms501kf03_probe(struct spi_device * spi)3121be9ca25SJingoo Han static int lms501kf03_probe(struct spi_device *spi)
3131be9ca25SJingoo Han {
3141be9ca25SJingoo Han struct lms501kf03 *lcd = NULL;
3151be9ca25SJingoo Han struct lcd_device *ld = NULL;
3161be9ca25SJingoo Han int ret = 0;
3171be9ca25SJingoo Han
3181be9ca25SJingoo Han lcd = devm_kzalloc(&spi->dev, sizeof(struct lms501kf03), GFP_KERNEL);
3191be9ca25SJingoo Han if (!lcd)
3201be9ca25SJingoo Han return -ENOMEM;
3211be9ca25SJingoo Han
3221be9ca25SJingoo Han /* lms501kf03 lcd panel uses 3-wire 9-bit SPI Mode. */
3231be9ca25SJingoo Han spi->bits_per_word = 9;
3241be9ca25SJingoo Han
3251be9ca25SJingoo Han ret = spi_setup(spi);
3261be9ca25SJingoo Han if (ret < 0) {
3271be9ca25SJingoo Han dev_err(&spi->dev, "spi setup failed.\n");
3281be9ca25SJingoo Han return ret;
3291be9ca25SJingoo Han }
3301be9ca25SJingoo Han
3311be9ca25SJingoo Han lcd->spi = spi;
3321be9ca25SJingoo Han lcd->dev = &spi->dev;
3331be9ca25SJingoo Han
334c512794cSJingoo Han lcd->lcd_pd = dev_get_platdata(&spi->dev);
3351be9ca25SJingoo Han if (!lcd->lcd_pd) {
3361be9ca25SJingoo Han dev_err(&spi->dev, "platform data is NULL\n");
3371be9ca25SJingoo Han return -EINVAL;
3381be9ca25SJingoo Han }
3391be9ca25SJingoo Han
3408358741aSJingoo Han ld = devm_lcd_device_register(&spi->dev, "lms501kf03", &spi->dev, lcd,
3411be9ca25SJingoo Han &lms501kf03_lcd_ops);
3421be9ca25SJingoo Han if (IS_ERR(ld))
3431be9ca25SJingoo Han return PTR_ERR(ld);
3441be9ca25SJingoo Han
3451be9ca25SJingoo Han lcd->ld = ld;
3461be9ca25SJingoo Han
3471be9ca25SJingoo Han if (!lcd->lcd_pd->lcd_enabled) {
3481be9ca25SJingoo Han /*
3491be9ca25SJingoo Han * if lcd panel was off from bootloader then
3501be9ca25SJingoo Han * current lcd status is powerdown and then
3511be9ca25SJingoo Han * it enables lcd panel.
3521be9ca25SJingoo Han */
3531be9ca25SJingoo Han lcd->power = FB_BLANK_POWERDOWN;
3541be9ca25SJingoo Han
3551be9ca25SJingoo Han lms501kf03_power(lcd, FB_BLANK_UNBLANK);
3561be9ca25SJingoo Han } else {
3571be9ca25SJingoo Han lcd->power = FB_BLANK_UNBLANK;
3581be9ca25SJingoo Han }
3591be9ca25SJingoo Han
360281ea16aSJingoo Han spi_set_drvdata(spi, lcd);
3611be9ca25SJingoo Han
3621be9ca25SJingoo Han dev_info(&spi->dev, "lms501kf03 panel driver has been probed.\n");
3631be9ca25SJingoo Han
3641be9ca25SJingoo Han return 0;
3651be9ca25SJingoo Han }
3661be9ca25SJingoo Han
lms501kf03_remove(struct spi_device * spi)367*a0386bbaSUwe Kleine-König static void lms501kf03_remove(struct spi_device *spi)
3681be9ca25SJingoo Han {
369281ea16aSJingoo Han struct lms501kf03 *lcd = spi_get_drvdata(spi);
3701be9ca25SJingoo Han
3711be9ca25SJingoo Han lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
3721be9ca25SJingoo Han }
3731be9ca25SJingoo Han
37426cd2a44SJingoo Han #ifdef CONFIG_PM_SLEEP
lms501kf03_suspend(struct device * dev)37526cd2a44SJingoo Han static int lms501kf03_suspend(struct device *dev)
3761be9ca25SJingoo Han {
37726cd2a44SJingoo Han struct lms501kf03 *lcd = dev_get_drvdata(dev);
3781be9ca25SJingoo Han
37926cd2a44SJingoo Han dev_dbg(dev, "lcd->power = %d\n", lcd->power);
3801be9ca25SJingoo Han
3811be9ca25SJingoo Han /*
3821be9ca25SJingoo Han * when lcd panel is suspend, lcd panel becomes off
3831be9ca25SJingoo Han * regardless of status.
3841be9ca25SJingoo Han */
3851be9ca25SJingoo Han return lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
3861be9ca25SJingoo Han }
3871be9ca25SJingoo Han
lms501kf03_resume(struct device * dev)38826cd2a44SJingoo Han static int lms501kf03_resume(struct device *dev)
3891be9ca25SJingoo Han {
39026cd2a44SJingoo Han struct lms501kf03 *lcd = dev_get_drvdata(dev);
3911be9ca25SJingoo Han
3921be9ca25SJingoo Han lcd->power = FB_BLANK_POWERDOWN;
3931be9ca25SJingoo Han
3941be9ca25SJingoo Han return lms501kf03_power(lcd, FB_BLANK_UNBLANK);
3951be9ca25SJingoo Han }
3961be9ca25SJingoo Han #endif
3971be9ca25SJingoo Han
39826cd2a44SJingoo Han static SIMPLE_DEV_PM_OPS(lms501kf03_pm_ops, lms501kf03_suspend,
39926cd2a44SJingoo Han lms501kf03_resume);
40026cd2a44SJingoo Han
lms501kf03_shutdown(struct spi_device * spi)4011be9ca25SJingoo Han static void lms501kf03_shutdown(struct spi_device *spi)
4021be9ca25SJingoo Han {
403281ea16aSJingoo Han struct lms501kf03 *lcd = spi_get_drvdata(spi);
4041be9ca25SJingoo Han
4051be9ca25SJingoo Han lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
4061be9ca25SJingoo Han }
4071be9ca25SJingoo Han
4081be9ca25SJingoo Han static struct spi_driver lms501kf03_driver = {
4091be9ca25SJingoo Han .driver = {
4101be9ca25SJingoo Han .name = "lms501kf03",
41126cd2a44SJingoo Han .pm = &lms501kf03_pm_ops,
4121be9ca25SJingoo Han },
4131be9ca25SJingoo Han .probe = lms501kf03_probe,
4141be9ca25SJingoo Han .remove = lms501kf03_remove,
4151be9ca25SJingoo Han .shutdown = lms501kf03_shutdown,
4161be9ca25SJingoo Han };
4171be9ca25SJingoo Han
4181be9ca25SJingoo Han module_spi_driver(lms501kf03_driver);
4191be9ca25SJingoo Han
4201be9ca25SJingoo Han MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
4211be9ca25SJingoo Han MODULE_DESCRIPTION("lms501kf03 LCD Driver");
4221be9ca25SJingoo Han MODULE_LICENSE("GPL");
423