jornada720_bl.c 3.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 *
 * Backlight driver for HP Jornada 700 series (710/720/728)
 * Copyright (C) 2006-2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 or any later version as published by the Free Software Foundation.
 *
 */

12 13
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

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
#include <linux/backlight.h>
#include <linux/device.h>
#include <linux/fb.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>

#include <mach/jornada720.h>
#include <mach/hardware.h>

#include <video/s1d13xxxfb.h>

#define BL_MAX_BRIGHT	255
#define BL_DEF_BRIGHT	25

static int jornada_bl_get_brightness(struct backlight_device *bd)
{
	int ret;

	/* check if backlight is on */
	if (!(PPSR & PPC_LDD1))
		return 0;

	jornada_ssp_start();

	/* cmd should return txdummy */
	ret = jornada_ssp_byte(GETBRIGHTNESS);

	if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
43
		pr_err("get brightness timeout\n");
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
		jornada_ssp_end();
		return -ETIMEDOUT;
	} else /* exchange txdummy for value */
		ret = jornada_ssp_byte(TXDUMMY);

	jornada_ssp_end();

	return (BL_MAX_BRIGHT - ret);
}

static int jornada_bl_update_status(struct backlight_device *bd)
{
	int ret = 0;

	jornada_ssp_start();

	/* If backlight is off then really turn it off */
	if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
		ret = jornada_ssp_byte(BRIGHTNESSOFF);
		if (ret != TXDUMMY) {
64
			pr_info("brightness off timeout\n");
65 66 67 68 69 70 71 72 73 74
			/* turn off backlight */
			PPSR &= ~PPC_LDD1;
			PPDR |= PPC_LDD1;
			ret = -ETIMEDOUT;
		}
	} else  /* turn on backlight */
		PPSR |= PPC_LDD1;

		/* send command to our mcu */
		if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
75
			pr_info("failed to set brightness\n");
76
			ret = -ETIMEDOUT;
77
			goto out;
78 79 80 81 82 83 84 85
		}

		/* at this point we expect that the mcu has accepted
		   our command and is waiting for our new value
		   please note that maximum brightness is 255,
		   but due to physical layout it is equal to 0, so we simply
		   invert the value (MAX VALUE - NEW VALUE). */
		if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
86
			pr_err("set brightness failed\n");
87 88 89 90 91 92 93 94 95 96 97
			ret = -ETIMEDOUT;
		}

		/* If infact we get an TXDUMMY as output we are happy and dont
		   make any further comments about it */
out:
	jornada_ssp_end();

	return ret;
}

98
static const struct backlight_ops jornada_bl_ops = {
99 100 101 102 103 104 105
	.get_brightness = jornada_bl_get_brightness,
	.update_status = jornada_bl_update_status,
	.options = BL_CORE_SUSPENDRESUME,
};

static int jornada_bl_probe(struct platform_device *pdev)
{
106
	struct backlight_properties props;
107 108 109
	int ret;
	struct backlight_device *bd;

110
	memset(&props, 0, sizeof(struct backlight_properties));
M
Matthew Garrett 已提交
111
	props.type = BACKLIGHT_RAW;
112 113 114
	props.max_brightness = BL_MAX_BRIGHT;
	bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
				       &jornada_bl_ops, &props);
115 116 117

	if (IS_ERR(bd)) {
		ret = PTR_ERR(bd);
118
		pr_err("failed to register device, err=%x\n", ret);
119 120 121 122 123 124 125 126 127 128 129
		return ret;
	}

	bd->props.power = FB_BLANK_UNBLANK;
	bd->props.brightness = BL_DEF_BRIGHT;
	/* note. make sure max brightness is set otherwise
	   you will get seemingly non-related errors when
	   trying to change brightness */
	jornada_bl_update_status(bd);

	platform_set_drvdata(pdev, bd);
130
	pr_info("HP Jornada 700 series backlight driver\n");
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

	return 0;
}

static int jornada_bl_remove(struct platform_device *pdev)
{
	struct backlight_device *bd = platform_get_drvdata(pdev);

	backlight_device_unregister(bd);

	return 0;
}

static struct platform_driver jornada_bl_driver = {
	.probe		= jornada_bl_probe,
	.remove		= jornada_bl_remove,
	.driver	= {
		.name	= "jornada_bl",
	},
};

152
module_platform_driver(jornada_bl_driver);
153 154 155 156

MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>");
MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver");
MODULE_LICENSE("GPL");