staging: olpc_dcon: move more variables into dcon_priv
This moves dcon_source and dcon_pending into the dcon_priv struct. Because these variables are used by the IRQ handler (which is registered in the model-specific callbacks), we end up needing to move dcon_priv into olpc_dcon.h. This also changes the IRQ registration to use the dcon_priv pointer as dev_id, instead of dcon_driver. Signed-off-by: Andres Salomon <dilinger@queued.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
097cd83a4c
commit
bbe963f1b9
@ -23,7 +23,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/reboot.h>
|
||||
@ -46,24 +45,6 @@ module_param(useaa, int, 0444);
|
||||
|
||||
static struct dcon_platform_data *pdata;
|
||||
|
||||
struct dcon_priv {
|
||||
struct i2c_client *client;
|
||||
struct fb_info *fbinfo;
|
||||
|
||||
struct work_struct switch_source;
|
||||
struct notifier_block reboot_nb;
|
||||
struct notifier_block fbevent_nb;
|
||||
|
||||
/* Shadow register for the DCON_REG_MODE register */
|
||||
u8 disp_mode;
|
||||
|
||||
/* Current output type; true == mono, false == color */
|
||||
bool mono;
|
||||
bool asleep;
|
||||
/* This get set while controlling fb blank state from the driver */
|
||||
bool ignore_fb_events;
|
||||
};
|
||||
|
||||
/* I2C structures */
|
||||
|
||||
/* Platform devices */
|
||||
@ -72,12 +53,6 @@ static struct platform_device *dcon_device;
|
||||
/* Backlight device */
|
||||
static struct backlight_device *dcon_bl_dev;
|
||||
|
||||
/* Current source, initialized at probe time */
|
||||
int dcon_source;
|
||||
|
||||
/* Desired source */
|
||||
int dcon_pending;
|
||||
|
||||
/* Variables used during switches */
|
||||
static int dcon_switched;
|
||||
static struct timespec dcon_irq_time;
|
||||
@ -119,7 +94,7 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
|
||||
if (is_init) {
|
||||
printk(KERN_INFO "olpc-dcon: Discovered DCON version %x\n",
|
||||
ver & 0xFF);
|
||||
rc = pdata->init();
|
||||
rc = pdata->init(dcon);
|
||||
if (rc != 0) {
|
||||
printk(KERN_ERR "olpc-dcon: Unable to init.\n");
|
||||
goto err;
|
||||
@ -366,9 +341,9 @@ static void dcon_source_switch(struct work_struct *work)
|
||||
struct dcon_priv *dcon = container_of(work, struct dcon_priv,
|
||||
switch_source);
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
int source = dcon_pending;
|
||||
int source = dcon->pending_src;
|
||||
|
||||
if (dcon_source == source)
|
||||
if (dcon->curr_src == source)
|
||||
return;
|
||||
|
||||
dcon_load_holdoff();
|
||||
@ -406,7 +381,7 @@ static void dcon_source_switch(struct work_struct *work)
|
||||
*/
|
||||
if (!dcon_blank_fb(dcon, false)) {
|
||||
printk(KERN_ERR "olpc-dcon: Failed to enter CPU mode\n");
|
||||
dcon_pending = DCON_SOURCE_DCON;
|
||||
dcon->pending_src = DCON_SOURCE_DCON;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -468,17 +443,17 @@ static void dcon_source_switch(struct work_struct *work)
|
||||
BUG();
|
||||
}
|
||||
|
||||
dcon_source = source;
|
||||
dcon->curr_src = source;
|
||||
}
|
||||
|
||||
static void dcon_set_source(struct dcon_priv *dcon, int arg)
|
||||
{
|
||||
if (dcon_pending == arg)
|
||||
if (dcon->pending_src == arg)
|
||||
return;
|
||||
|
||||
dcon_pending = arg;
|
||||
dcon->pending_src = arg;
|
||||
|
||||
if ((dcon_source != arg) && !work_pending(&dcon->switch_source))
|
||||
if ((dcon->curr_src != arg) && !work_pending(&dcon->switch_source))
|
||||
schedule_work(&dcon->switch_source);
|
||||
}
|
||||
|
||||
@ -524,7 +499,8 @@ static ssize_t dcon_sleep_show(struct device *dev,
|
||||
static ssize_t dcon_freeze_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", dcon_source == DCON_SOURCE_DCON ? 1 : 0);
|
||||
struct dcon_priv *dcon = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%d\n", dcon->curr_src == DCON_SOURCE_DCON ? 1 : 0);
|
||||
}
|
||||
|
||||
static ssize_t dcon_mono_show(struct device *dev,
|
||||
@ -765,7 +741,7 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
platform_device_unregister(dcon_device);
|
||||
dcon_device = NULL;
|
||||
eirq:
|
||||
free_irq(DCON_IRQ, &dcon_driver);
|
||||
free_irq(DCON_IRQ, dcon);
|
||||
einit:
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(dcon);
|
||||
@ -782,7 +758,7 @@ static int dcon_remove(struct i2c_client *client)
|
||||
unregister_reboot_notifier(&dcon->reboot_nb);
|
||||
atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb);
|
||||
|
||||
free_irq(DCON_IRQ, &dcon_driver);
|
||||
free_irq(DCON_IRQ, dcon);
|
||||
|
||||
if (dcon_bl_dev != NULL)
|
||||
backlight_device_unregister(dcon_bl_dev);
|
||||
@ -826,6 +802,7 @@ static int dcon_resume(struct i2c_client *client)
|
||||
|
||||
irqreturn_t dcon_interrupt(int irq, void *id)
|
||||
{
|
||||
struct dcon_priv *dcon = id;
|
||||
int status = pdata->read_status();
|
||||
|
||||
if (status == -1)
|
||||
@ -851,7 +828,7 @@ irqreturn_t dcon_interrupt(int irq, void *id)
|
||||
* of the DCON happened long before this point.
|
||||
* see http://dev.laptop.org/ticket/9869
|
||||
*/
|
||||
if (dcon_source != dcon_pending && !dcon_switched) {
|
||||
if (dcon->curr_src != dcon->pending_src && !dcon_switched) {
|
||||
dcon_switched = 1;
|
||||
getnstimeofday(&dcon_irq_time);
|
||||
wake_up(&dcon_wait_queue);
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef OLPC_DCON_H_
|
||||
#define OLPC_DCON_H_
|
||||
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
/* DCON registers */
|
||||
|
||||
#define DCON_REG_ID 0
|
||||
@ -44,8 +47,32 @@
|
||||
/* Interrupt */
|
||||
#define DCON_IRQ 6
|
||||
|
||||
struct dcon_priv {
|
||||
struct i2c_client *client;
|
||||
struct fb_info *fbinfo;
|
||||
|
||||
struct work_struct switch_source;
|
||||
struct notifier_block reboot_nb;
|
||||
struct notifier_block fbevent_nb;
|
||||
|
||||
/* Shadow register for the DCON_REG_MODE register */
|
||||
u8 disp_mode;
|
||||
|
||||
/* Current source, initialized at probe time */
|
||||
int curr_src;
|
||||
|
||||
/* Desired source */
|
||||
int pending_src;
|
||||
|
||||
/* Current output type; true == mono, false == color */
|
||||
bool mono;
|
||||
bool asleep;
|
||||
/* This get set while controlling fb blank state from the driver */
|
||||
bool ignore_fb_events;
|
||||
};
|
||||
|
||||
struct dcon_platform_data {
|
||||
int (*init)(void);
|
||||
int (*init)(struct dcon_priv *);
|
||||
void (*bus_stabilize_wiggle)(void);
|
||||
void (*set_dconload)(int);
|
||||
u8 (*read_status)(void);
|
||||
@ -53,10 +80,7 @@ struct dcon_platform_data {
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
extern int dcon_source;
|
||||
extern int dcon_pending;
|
||||
extern irqreturn_t dcon_interrupt(int irq, void *id);
|
||||
extern struct i2c_driver dcon_driver;
|
||||
|
||||
#ifdef CONFIG_FB_OLPC_DCON_1
|
||||
extern struct dcon_platform_data dcon_pdata_xo_1;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "olpc_dcon.h"
|
||||
|
||||
static int dcon_init_xo_1(void)
|
||||
static int dcon_init_xo_1(struct dcon_priv *dcon)
|
||||
{
|
||||
unsigned char lob;
|
||||
|
||||
@ -54,10 +54,10 @@ static int dcon_init_xo_1(void)
|
||||
* then a value is set. So, future readings of the pin can use
|
||||
* READ_BACK, but the first one cannot. Awesome, huh?
|
||||
*/
|
||||
dcon_source = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL)
|
||||
dcon->curr_src = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL)
|
||||
? DCON_SOURCE_CPU
|
||||
: DCON_SOURCE_DCON;
|
||||
dcon_pending = dcon_source;
|
||||
dcon->pending_src = dcon->curr_src;
|
||||
|
||||
/* Set the directions for the GPIO pins */
|
||||
gpio_direction_input(OLPC_GPIO_DCON_STAT0);
|
||||
@ -65,7 +65,7 @@ static int dcon_init_xo_1(void)
|
||||
gpio_direction_input(OLPC_GPIO_DCON_IRQ);
|
||||
gpio_direction_input(OLPC_GPIO_DCON_BLANK);
|
||||
gpio_direction_output(OLPC_GPIO_DCON_LOAD,
|
||||
dcon_source == DCON_SOURCE_CPU);
|
||||
dcon->curr_src == DCON_SOURCE_CPU);
|
||||
|
||||
/* Set up the interrupt mappings */
|
||||
|
||||
@ -81,7 +81,7 @@ static int dcon_init_xo_1(void)
|
||||
outb(lob, 0x4d0);
|
||||
|
||||
/* Register the interupt handler */
|
||||
if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", &dcon_driver)) {
|
||||
if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) {
|
||||
printk(KERN_ERR "olpc-dcon: failed to request DCON's irq\n");
|
||||
goto err_req_irq;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ static int dcon_was_irq(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dcon_init_xo_1_5(void)
|
||||
static int dcon_init_xo_1_5(struct dcon_priv *dcon)
|
||||
{
|
||||
unsigned int irq;
|
||||
u_int8_t tmp;
|
||||
@ -96,20 +96,19 @@ static int dcon_init_xo_1_5(void)
|
||||
|
||||
/* Determine the current state of DCONLOAD, likely set by firmware */
|
||||
/* GPIO1 */
|
||||
dcon_source = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ?
|
||||
dcon->curr_src = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ?
|
||||
DCON_SOURCE_CPU : DCON_SOURCE_DCON;
|
||||
dcon_pending = dcon_source;
|
||||
dcon->pending_src = dcon->curr_src;
|
||||
|
||||
pci_dev_put(pdev);
|
||||
|
||||
/* we're sharing the IRQ with ACPI */
|
||||
irq = acpi_gbl_FADT.sci_interrupt;
|
||||
if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", &dcon_driver)) {
|
||||
if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) {
|
||||
printk(KERN_ERR PREFIX "DCON (IRQ%d) allocation failed\n", irq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user