summaryrefslogtreecommitdiff
path: root/arch/arm/plat-samsung/dev-backlight.c
blob: 2157c5b539e6c9ad88baab1b41985b27f525042d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* linux/arch/arm/plat-samsung/dev-backlight.c
 *
 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
 *              http://www.samsung.com
 *
 * Common infrastructure for PWM Backlight for Samsung boards
 *
 * 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/gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/pwm_backlight.h>

#include <plat/devs.h>
#include <plat/gpio-cfg.h>
#include <plat/backlight.h>

struct samsung_bl_drvdata {
	struct platform_pwm_backlight_data plat_data;
	struct samsung_bl_gpio_info *gpio_info;
};

static int samsung_bl_init(struct device *dev)
{
	int ret = 0;
	struct platform_pwm_backlight_data *pdata = dev->platform_data;
	struct samsung_bl_drvdata *drvdata = container_of(pdata,
					struct samsung_bl_drvdata, plat_data);
	struct samsung_bl_gpio_info *bl_gpio_info = drvdata->gpio_info;

	ret = gpio_request(bl_gpio_info->no, "Backlight");
	if (ret) {
		printk(KERN_ERR "failed to request GPIO for LCD Backlight\n");
		return ret;
	}

	/* Configure GPIO pin with specific GPIO function for PWM timer */
	s3c_gpio_cfgpin(bl_gpio_info->no, bl_gpio_info->func);

	return 0;
}

static void samsung_bl_exit(struct device *dev)
{
	struct platform_pwm_backlight_data *pdata = dev->platform_data;
	struct samsung_bl_drvdata *drvdata = container_of(pdata,
					struct samsung_bl_drvdata, plat_data);
	struct samsung_bl_gpio_info *bl_gpio_info = drvdata->gpio_info;

	s3c_gpio_cfgpin(bl_gpio_info->no, S3C_GPIO_OUTPUT);
	gpio_free(bl_gpio_info->no);
}

/* Initialize few important fields of platform_pwm_backlight_data
 * structure with default values. These fields can be overridden by
 * board-specific values sent from machine file.
 * For ease of operation, these fields are initialized with values
 * used by most samsung boards.
 * Users has the option of sending info about other parameters
 * for their specific boards
 */

static struct samsung_bl_drvdata samsung_dfl_bl_data __initdata = {
	.plat_data = {
		.max_brightness = 255,
		.dft_brightness = 255,
		.pwm_period_ns  = 78770,
		.enable_gpio    = -1,
		.init           = samsung_bl_init,
		.exit           = samsung_bl_exit,
	},
};

static struct platform_device samsung_dfl_bl_device __initdata = {
	.name		= "pwm-backlight",
};

/* samsung_bl_set - Set board specific data (if any) provided by user for
 * PWM Backlight control and register specific PWM and backlight device.
 * @gpio_info:	structure containing GPIO info for PWM timer
 * @bl_data:	structure containing Backlight control data
 */
void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
	struct platform_pwm_backlight_data *bl_data)
{
	int ret = 0;
	struct platform_device *samsung_bl_device;
	struct samsung_bl_drvdata *samsung_bl_drvdata;
	struct platform_pwm_backlight_data *samsung_bl_data;

	samsung_bl_device = kmemdup(&samsung_dfl_bl_device,
			sizeof(struct platform_device), GFP_KERNEL);
	if (!samsung_bl_device) {
		printk(KERN_ERR "%s: no memory for platform dev\n", __func__);
		return;
	}

	samsung_bl_drvdata = kmemdup(&samsung_dfl_bl_data,
				sizeof(samsung_dfl_bl_data), GFP_KERNEL);
	if (!samsung_bl_drvdata) {
		printk(KERN_ERR "%s: no memory for platform dev\n", __func__);
		goto err_data;
	}
	samsung_bl_device->dev.platform_data = &samsung_bl_drvdata->plat_data;
	samsung_bl_drvdata->gpio_info = gpio_info;
	samsung_bl_data = &samsung_bl_drvdata->plat_data;

	/* Copy board specific data provided by user */
	samsung_bl_data->pwm_id = bl_data->pwm_id;
	samsung_bl_device->dev.parent = &samsung_device_pwm.dev;

	if (bl_data->max_brightness)
		samsung_bl_data->max_brightness = bl_data->max_brightness;
	if (bl_data->dft_brightness)
		samsung_bl_data->dft_brightness = bl_data->dft_brightness;
	if (bl_data->lth_brightness)
		samsung_bl_data->lth_brightness = bl_data->lth_brightness;
	if (bl_data->pwm_period_ns)
		samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;
	if (bl_data->enable_gpio >= 0)
		samsung_bl_data->enable_gpio = bl_data->enable_gpio;
	if (bl_data->init)
		samsung_bl_data->init = bl_data->init;
	if (bl_data->notify)
		samsung_bl_data->notify = bl_data->notify;
	if (bl_data->notify_after)
		samsung_bl_data->notify_after = bl_data->notify_after;
	if (bl_data->exit)
		samsung_bl_data->exit = bl_data->exit;
	if (bl_data->check_fb)
		samsung_bl_data->check_fb = bl_data->check_fb;

	/* Register the Backlight dev */
	ret = platform_device_register(samsung_bl_device);
	if (ret) {
		printk(KERN_ERR "failed to register backlight device: %d\n", ret);
		goto err_plat_reg2;
	}

	return;

err_plat_reg2:
	kfree(samsung_bl_data);
err_data:
	kfree(samsung_bl_device);
	return;
}