platform_lcd.c 3.5 KB
Newer Older
B
Ben Dooks 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/* drivers/video/backlight/platform_lcd.c
 *
 * Copyright 2008 Simtec Electronics
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * Generic platform-device LCD power control interface.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
*/

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/lcd.h>
19
#include <linux/of.h>
20
#include <linux/slab.h>
B
Ben Dooks 已提交
21 22 23 24 25 26 27 28 29

#include <video/platform_lcd.h>

struct platform_lcd {
	struct device		*us;
	struct lcd_device	*lcd;
	struct plat_lcd_data	*pdata;

	unsigned int		 power;
30
	unsigned int		 suspended:1;
B
Ben Dooks 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
};

static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
{
	return lcd_get_data(lcd);
}

static int platform_lcd_get_power(struct lcd_device *lcd)
{
	struct platform_lcd *plcd = to_our_lcd(lcd);

	return plcd->power;
}

static int platform_lcd_set_power(struct lcd_device *lcd, int power)
{
	struct platform_lcd *plcd = to_our_lcd(lcd);
	int lcd_power = 1;

	if (power == FB_BLANK_POWERDOWN || plcd->suspended)
		lcd_power = 0;

	plcd->pdata->set_power(plcd->pdata, lcd_power);
	plcd->power = power;

	return 0;
}

static int platform_lcd_match(struct lcd_device *lcd, struct fb_info *info)
{
	struct platform_lcd *plcd = to_our_lcd(lcd);
	struct plat_lcd_data *pdata = plcd->pdata;

	if (pdata->match_fb)
		return pdata->match_fb(pdata, info);

	return plcd->us->parent == info->device;
}

static struct lcd_ops platform_lcd_ops = {
	.get_power	= platform_lcd_get_power,
	.set_power	= platform_lcd_set_power,
	.check_fb	= platform_lcd_match,
};

76
static int platform_lcd_probe(struct platform_device *pdev)
B
Ben Dooks 已提交
77 78 79 80 81 82
{
	struct plat_lcd_data *pdata;
	struct platform_lcd *plcd;
	struct device *dev = &pdev->dev;
	int err;

J
Jingoo Han 已提交
83
	pdata = dev_get_platdata(&pdev->dev);
B
Ben Dooks 已提交
84 85 86 87 88
	if (!pdata) {
		dev_err(dev, "no platform data supplied\n");
		return -EINVAL;
	}

89 90 91 92 93 94
	if (pdata->probe) {
		err = pdata->probe(pdata);
		if (err)
			return err;
	}

95 96
	plcd = devm_kzalloc(&pdev->dev, sizeof(struct platform_lcd),
			    GFP_KERNEL);
97
	if (!plcd)
B
Ben Dooks 已提交
98 99 100 101
		return -ENOMEM;

	plcd->us = dev;
	plcd->pdata = pdata;
102 103
	plcd->lcd = devm_lcd_device_register(&pdev->dev, dev_name(dev), dev,
						plcd, &platform_lcd_ops);
B
Ben Dooks 已提交
104 105
	if (IS_ERR(plcd->lcd)) {
		dev_err(dev, "cannot register lcd device\n");
106
		return PTR_ERR(plcd->lcd);
B
Ben Dooks 已提交
107 108 109
	}

	platform_set_drvdata(pdev, plcd);
110 111
	platform_lcd_set_power(plcd->lcd, FB_BLANK_NORMAL);

B
Ben Dooks 已提交
112 113 114
	return 0;
}

115
#ifdef CONFIG_PM_SLEEP
116
static int platform_lcd_suspend(struct device *dev)
B
Ben Dooks 已提交
117
{
118
	struct platform_lcd *plcd = dev_get_drvdata(dev);
B
Ben Dooks 已提交
119 120 121 122 123 124 125

	plcd->suspended = 1;
	platform_lcd_set_power(plcd->lcd, plcd->power);

	return 0;
}

126
static int platform_lcd_resume(struct device *dev)
B
Ben Dooks 已提交
127
{
128
	struct platform_lcd *plcd = dev_get_drvdata(dev);
B
Ben Dooks 已提交
129 130 131 132 133 134

	plcd->suspended = 0;
	platform_lcd_set_power(plcd->lcd, plcd->power);

	return 0;
}
135
#endif
136 137 138

static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend,
			platform_lcd_resume);
B
Ben Dooks 已提交
139

140 141 142 143 144 145 146 147
#ifdef CONFIG_OF
static const struct of_device_id platform_lcd_of_match[] = {
	{ .compatible = "platform-lcd" },
	{},
};
MODULE_DEVICE_TABLE(of, platform_lcd_of_match);
#endif

B
Ben Dooks 已提交
148 149 150 151
static struct platform_driver platform_lcd_driver = {
	.driver		= {
		.name	= "platform-lcd",
		.owner	= THIS_MODULE,
152
		.pm	= &platform_lcd_pm_ops,
153
		.of_match_table = of_match_ptr(platform_lcd_of_match),
B
Ben Dooks 已提交
154 155 156 157
	},
	.probe		= platform_lcd_probe,
};

158
module_platform_driver(platform_lcd_driver);
B
Ben Dooks 已提交
159 160 161 162

MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:platform-lcd");