Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 942bb7b5 authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

Merge branch 'wm97xx'

parents 48bdce4a 34d27853
Loading
Loading
Loading
Loading
+48 −8
Original line number Original line Diff line number Diff line
@@ -261,6 +261,23 @@ void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir,
}
}
EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
EXPORT_SYMBOL_GPL(wm97xx_config_gpio);


/*
 * Configure the WM97XX_PRP value to use while system is suspended.
 * If a value other than 0 is set then WM97xx pen detection will be
 * left enabled in the configured mode while the system is in suspend,
 * the device has users and suspend has not been disabled via the
 * wakeup sysfs entries.
 *
 * @wm:   WM97xx device to configure
 * @mode: WM97XX_PRP value to configure while suspended
 */
void wm97xx_set_suspend_mode(struct wm97xx *wm, u16 mode)
{
	wm->suspend_mode = mode;
	device_init_wakeup(&wm->input_dev->dev, mode != 0);
}
EXPORT_SYMBOL_GPL(wm97xx_set_suspend_mode);

/*
/*
 * Handle a pen down interrupt.
 * Handle a pen down interrupt.
 */
 */
@@ -328,18 +345,18 @@ static void wm97xx_pen_irq_worker(struct work_struct *work)
 *
 *
 * We have to disable the codec interrupt in the handler because it
 * We have to disable the codec interrupt in the handler because it
 * can take upto 1ms to clear the interrupt source. We schedule a task
 * can take upto 1ms to clear the interrupt source. We schedule a task
 * in a work queue to do the actual interaction with the chip (it
 * in a work queue to do the actual interaction with the chip.  The
 * doesn't matter if we end up reenqueing it before it is executed
 * interrupt is then enabled again in the slow handler when the source
 * since we don't touch the chip until it has run).  The interrupt is
 * has been cleared.
 * then enabled again in the slow handler when the source has been
 * cleared.
 */
 */
static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
{
{
	struct wm97xx *wm = dev_id;
	struct wm97xx *wm = dev_id;


	if (!work_pending(&wm->pen_event_work)) {
		wm->mach_ops->irq_enable(wm, 0);
		wm->mach_ops->irq_enable(wm, 0);
		queue_work(wm->ts_workq, &wm->pen_event_work);
		queue_work(wm->ts_workq, &wm->pen_event_work);
	}


	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}
@@ -355,7 +372,8 @@ static int wm97xx_init_pen_irq(struct wm97xx *wm)
	 * provided. */
	 * provided. */
	BUG_ON(!wm->mach_ops->irq_enable);
	BUG_ON(!wm->mach_ops->irq_enable);


	if (request_irq(wm->pen_irq, wm97xx_pen_interrupt, IRQF_SHARED,
	if (request_irq(wm->pen_irq, wm97xx_pen_interrupt,
			IRQF_SHARED | IRQF_SAMPLE_RANDOM,
			"wm97xx-pen", wm)) {
			"wm97xx-pen", wm)) {
		dev_err(wm->dev,
		dev_err(wm->dev,
			"Failed to register pen down interrupt, polling");
			"Failed to register pen down interrupt, polling");
@@ -688,10 +706,32 @@ static int wm97xx_remove(struct device *dev)
static int wm97xx_suspend(struct device *dev, pm_message_t state)
static int wm97xx_suspend(struct device *dev, pm_message_t state)
{
{
	struct wm97xx *wm = dev_get_drvdata(dev);
	struct wm97xx *wm = dev_get_drvdata(dev);
	u16 reg;
	int suspend_mode;

	if (device_may_wakeup(&wm->input_dev->dev))
		suspend_mode = wm->suspend_mode;
	else
		suspend_mode = 0;


	if (wm->input_dev->users)
	if (wm->input_dev->users)
		cancel_delayed_work_sync(&wm->ts_reader);
		cancel_delayed_work_sync(&wm->ts_reader);


	/* Power down the digitiser (bypassing the cache for resume) */
	reg = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER2);
	reg &= ~WM97XX_PRP_DET_DIG;
	if (wm->input_dev->users)
		reg |= suspend_mode;
	wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg);

	/* WM9713 has an additional power bit - turn it off if there
	 * are no users or if suspend mode is zero. */
	if (wm->id == WM9713_ID2 &&
	    (!wm->input_dev->users || !suspend_mode)) {
		reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
		wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
	}

	return 0;
	return 0;
}
}


+3 −0
Original line number Original line Diff line number Diff line
@@ -282,6 +282,7 @@ struct wm97xx {
	unsigned pen_is_down:1;		/* Pen is down */
	unsigned pen_is_down:1;		/* Pen is down */
	unsigned aux_waiting:1;		/* aux measurement waiting */
	unsigned aux_waiting:1;		/* aux measurement waiting */
	unsigned pen_probably_down:1;	/* used in polling mode */
	unsigned pen_probably_down:1;	/* used in polling mode */
	u16 suspend_mode;               /* PRP in suspend mode */
};
};


/*
/*
@@ -297,6 +298,8 @@ void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio,
				     enum wm97xx_gpio_sticky sticky,
				     enum wm97xx_gpio_sticky sticky,
				     enum wm97xx_gpio_wake wake);
				     enum wm97xx_gpio_wake wake);


void wm97xx_set_suspend_mode(struct wm97xx *wm, u16 mode);

/* codec AC97 IO access */
/* codec AC97 IO access */
int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);
void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);