Commit c6e6e58c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'staging-4.6-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging and IIO driver fixes from Greg KH:
 "Here are some IIO driver fixes, along with two staging driver fixes
  for 4.6-rc3.

  One staging driver patch reverts the deletion of a driver that
  happened in 4.6-rc1.  We thought that laptop.org was dead, but it's
  still alive and kicking, and has users that were mad we broke their
  hardware by deleting a driver for their machines.  So that driver is
  added back and everyone is happy again.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'staging-4.6-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging:
  Revert "Staging: olpc_dcon: Remove obsolete driver"
  staging/rdma/hfi1: select CRC32
  iio: gyro: bmg160: fix buffer read values
  iio: gyro: bmg160: fix endianness when reading axes
  iio: accel: bmc150: fix endianness when reading axes
  iio: st_magn: always define ST_MAGN_TRIGGER_SET_STATE
  iio: fix config watermark initial value
  iio: health: max30100: correct FIFO check condition
  iio: imu: Fix inv_mpu6050 dependencies
  iio: adc: Fix build error of missing devm_ioremap_resource on UM
  iio: light: apds9960: correct FIFO check condition
  iio: adc: max1363: correct reference voltage
  iio: adc: max1363: add missing adc to max1363_id
parents fb41b4be 53c43c5c
......@@ -10595,6 +10595,14 @@ L: linux-tegra@vger.kernel.org
S: Maintained
F: drivers/staging/nvec/
STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
M: Jens Frederich <jfrederich@gmail.com>
M: Daniel Drake <dsd@laptop.org>
M: Jon Nettleton <jon.nettleton@gmail.com>
W: http://wiki.laptop.org/go/DCON
S: Maintained
F: drivers/staging/olpc_dcon/
STAGING - REALTEK RTL8712U DRIVERS
M: Larry Finger <Larry.Finger@lwfinger.net>
M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
......
......@@ -547,7 +547,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
{
int ret;
int axis = chan->scan_index;
unsigned int raw_val;
__le16 raw_val;
mutex_lock(&data->mutex);
ret = bmc150_accel_set_power_state(data, true);
......@@ -557,14 +557,14 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
}
ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis),
&raw_val, 2);
&raw_val, sizeof(raw_val));
if (ret < 0) {
dev_err(data->dev, "Error reading axis %d\n", axis);
bmc150_accel_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
}
*val = sign_extend32(raw_val >> chan->scan_type.shift,
*val = sign_extend32(le16_to_cpu(raw_val) >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
ret = bmc150_accel_set_power_state(data, false);
mutex_unlock(&data->mutex);
......@@ -988,6 +988,7 @@ static const struct iio_event_spec bmc150_accel_event = {
.realbits = (bits), \
.storagebits = 16, \
.shift = 16 - (bits), \
.endianness = IIO_LE, \
}, \
.event_spec = &bmc150_accel_event, \
.num_event_specs = 1 \
......
......@@ -134,6 +134,7 @@ config AT91_ADC
config AT91_SAMA5D2_ADC
tristate "Atmel AT91 SAMA5D2 ADC"
depends on ARCH_AT91 || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for Atmel SAMA5D2 ADC which is
available on SAMA5D2 SoC family.
......
......@@ -1386,7 +1386,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
},
[max11644] = {
.bits = 12,
.int_vref_mv = 2048,
.int_vref_mv = 4096,
.mode_list = max11644_mode_list,
.num_modes = ARRAY_SIZE(max11644_mode_list),
.default_mode = s0to1,
......@@ -1396,7 +1396,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
},
[max11645] = {
.bits = 12,
.int_vref_mv = 4096,
.int_vref_mv = 2048,
.mode_list = max11644_mode_list,
.num_modes = ARRAY_SIZE(max11644_mode_list),
.default_mode = s0to1,
......@@ -1406,7 +1406,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
},
[max11646] = {
.bits = 10,
.int_vref_mv = 2048,
.int_vref_mv = 4096,
.mode_list = max11644_mode_list,
.num_modes = ARRAY_SIZE(max11644_mode_list),
.default_mode = s0to1,
......@@ -1416,7 +1416,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
},
[max11647] = {
.bits = 10,
.int_vref_mv = 4096,
.int_vref_mv = 2048,
.mode_list = max11644_mode_list,
.num_modes = ARRAY_SIZE(max11644_mode_list),
.default_mode = s0to1,
......@@ -1680,6 +1680,10 @@ static const struct i2c_device_id max1363_id[] = {
{ "max11615", max11615 },
{ "max11616", max11616 },
{ "max11617", max11617 },
{ "max11644", max11644 },
{ "max11645", max11645 },
{ "max11646", max11646 },
{ "max11647", max11647 },
{}
};
......
......@@ -452,7 +452,7 @@ static int bmg160_get_temp(struct bmg160_data *data, int *val)
static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val)
{
int ret;
unsigned int raw_val;
__le16 raw_val;
mutex_lock(&data->mutex);
ret = bmg160_set_power_state(data, true);
......@@ -462,7 +462,7 @@ static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val)
}
ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(axis), &raw_val,
2);
sizeof(raw_val));
if (ret < 0) {
dev_err(data->dev, "Error reading axis %d\n", axis);
bmg160_set_power_state(data, false);
......@@ -470,7 +470,7 @@ static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val)
return ret;
}
*val = sign_extend32(raw_val, 15);
*val = sign_extend32(le16_to_cpu(raw_val), 15);
ret = bmg160_set_power_state(data, false);
mutex_unlock(&data->mutex);
if (ret < 0)
......@@ -733,6 +733,7 @@ static const struct iio_event_spec bmg160_event = {
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_LE, \
}, \
.event_spec = &bmg160_event, \
.num_event_specs = 1 \
......@@ -780,7 +781,7 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p)
mutex_unlock(&data->mutex);
goto err;
}
data->buffer[i++] = ret;
data->buffer[i++] = val;
}
mutex_unlock(&data->mutex);
......
......@@ -238,12 +238,13 @@ static irqreturn_t max30100_interrupt_handler(int irq, void *private)
mutex_lock(&data->lock);
while (cnt-- || (cnt = max30100_fifo_count(data) > 0)) {
while (cnt || (cnt = max30100_fifo_count(data) > 0)) {
ret = max30100_read_measurement(data);
if (ret)
break;
iio_push_to_buffers(data->indio_dev, data->buffer);
cnt--;
}
mutex_unlock(&data->lock);
......
......@@ -9,9 +9,8 @@ config INV_MPU6050_IIO
config INV_MPU6050_I2C
tristate "Invensense MPU6050 devices (I2C)"
depends on I2C
depends on I2C_MUX
select INV_MPU6050_IIO
select I2C_MUX
select REGMAP_I2C
help
This driver supports the Invensense MPU6050 devices.
......
......@@ -653,6 +653,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
unsigned int modes;
memset(config, 0, sizeof(*config));
config->watermark = ~0;
/*
* If there is just one buffer and we are removing it there is nothing
......
......@@ -769,7 +769,7 @@ static void apds9960_read_gesture_fifo(struct apds9960_data *data)
mutex_lock(&data->lock);
data->gesture_mode_running = 1;
while (cnt-- || (cnt = apds9660_fifo_is_empty(data) > 0)) {
while (cnt || (cnt = apds9660_fifo_is_empty(data) > 0)) {
ret = regmap_bulk_read(data->regmap, APDS9960_REG_GFIFO_BASE,
&data->buffer, 4);
......@@ -777,6 +777,7 @@ static void apds9960_read_gesture_fifo(struct apds9960_data *data)
goto err_read;
iio_push_to_buffers(data->indio_dev, data->buffer);
cnt--;
}
err_read:
......
......@@ -44,6 +44,7 @@ static inline int st_magn_allocate_ring(struct iio_dev *indio_dev)
static inline void st_magn_deallocate_ring(struct iio_dev *indio_dev)
{
}
#define ST_MAGN_TRIGGER_SET_STATE NULL
#endif /* CONFIG_IIO_BUFFER */
#endif /* ST_MAGN_H */
......@@ -30,6 +30,8 @@ source "drivers/staging/wlan-ng/Kconfig"
source "drivers/staging/comedi/Kconfig"
source "drivers/staging/olpc_dcon/Kconfig"
source "drivers/staging/rtl8192u/Kconfig"
source "drivers/staging/rtl8192e/Kconfig"
......
......@@ -4,6 +4,7 @@ obj-y += media/
obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_R8712U) += rtl8712/
......
config FB_OLPC_DCON
tristate "One Laptop Per Child Display CONtroller support"
depends on OLPC && FB
depends on I2C
depends on (GPIO_CS5535 || GPIO_CS5535=n)
select BACKLIGHT_CLASS_DEVICE
---help---
In order to support very low power operation, the XO laptop uses a
secondary Display CONtroller, or DCON. This secondary controller
is present in the video pipeline between the primary display
controller (integrate into the processor or chipset) and the LCD
panel. It allows the main processor/display controller to be
completely powered off while still retaining an image on the display.
This controller is only available on OLPC platforms. Unless you have
one of these platforms, you will want to say 'N'.
config FB_OLPC_DCON_1
bool "OLPC XO-1 DCON support"
depends on FB_OLPC_DCON && GPIO_CS5535
default y
---help---
Enable support for the DCON in XO-1 model laptops. The kernel
communicates with the DCON using model-specific code. If you
have an XO-1 (or if you're unsure what model you have), you should
say 'Y'.
config FB_OLPC_DCON_1_5
bool "OLPC XO-1.5 DCON support"
depends on FB_OLPC_DCON && ACPI
default y
---help---
Enable support for the DCON in XO-1.5 model laptops. The kernel
communicates with the DCON using model-specific code. If you
have an XO-1.5 (or if you're unsure what model you have), you
should say 'Y'.
olpc-dcon-objs += olpc_dcon.o
olpc-dcon-$(CONFIG_FB_OLPC_DCON_1) += olpc_dcon_xo_1.o
olpc-dcon-$(CONFIG_FB_OLPC_DCON_1_5) += olpc_dcon_xo_1_5.o
obj-$(CONFIG_FB_OLPC_DCON) += olpc-dcon.o
TODO:
- see if vx855 gpio API can be made similar enough to cs5535 so we can
share more code
- allow simultaneous XO-1 and XO-1.5 support
Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
copy:
Daniel Drake <dsd@laptop.org>
Jens Frederich <jfrederich@gmail.com>
/*
* Mainly by David Woodhouse, somewhat modified by Jordan Crouse
*
* Copyright © 2006-2007 Red Hat, Inc.
* Copyright © 2006-2007 Advanced Micro Devices, Inc.
* Copyright © 2009 VIA Technology, Inc.
* Copyright (c) 2010-2011 Andres Salomon <dilinger@queued.net>
*
* This program is free software. You can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/fb.h>
#include <linux/console.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/backlight.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/ctype.h>
#include <linux/reboot.h>
#include <linux/olpc-ec.h>
#include <asm/tsc.h>
#include <asm/olpc.h>
#include "olpc_dcon.h"
/* Module definitions */
static ushort resumeline = 898;
module_param(resumeline, ushort, 0444);
static struct dcon_platform_data *pdata;
/* I2C structures */
/* Platform devices */
static struct platform_device *dcon_device;
static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END };
static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val)
{
return i2c_smbus_write_word_data(dcon->client, reg, val);
}
static s32 dcon_read(struct dcon_priv *dcon, u8 reg)
{
return i2c_smbus_read_word_data(dcon->client, reg);
}
/* ===== API functions - these are called by a variety of users ==== */
static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
{
u16 ver;
int rc = 0;
ver = dcon_read(dcon, DCON_REG_ID);
if ((ver >> 8) != 0xDC) {
pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver);
rc = -ENXIO;
goto err;
}
if (is_init) {
pr_info("Discovered DCON version %x\n", ver & 0xFF);
rc = pdata->init(dcon);
if (rc != 0) {
pr_err("Unable to init.\n");
goto err;
}
}
if (ver < 0xdc02) {
dev_err(&dcon->client->dev,
"DCON v1 is unsupported, giving up..\n");
rc = -ENODEV;
goto err;
}
/* SDRAM setup/hold time */
dcon_write(dcon, 0x3a, 0xc040);
dcon_write(dcon, DCON_REG_MEM_OPT_A, 0x0000); /* clear option bits */
dcon_write(dcon, DCON_REG_MEM_OPT_A,
MEM_DLL_CLOCK_DELAY | MEM_POWER_DOWN);
dcon_write(dcon, DCON_REG_MEM_OPT_B, MEM_SOFT_RESET);
/* Colour swizzle, AA, no passthrough, backlight */
if (is_init) {
dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE |
MODE_CSWIZZLE | MODE_COL_AA;
}
dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
/* Set the scanline to interrupt on during resume */
dcon_write(dcon, DCON_REG_SCAN_INT, resumeline);
err:
return rc;
}
/*
* The smbus doesn't always come back due to what is believed to be
* hardware (power rail) bugs. For older models where this is known to
* occur, our solution is to attempt to wait for the bus to stabilize;
* if it doesn't happen, cut power to the dcon, repower it, and wait
* for the bus to stabilize. Rinse, repeat until we have a working
* smbus. For newer models, we simply BUG(); we want to know if this
* still happens despite the power fixes that have been made!
*/
static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down)
{
unsigned long timeout;
u8 pm;
int x;
power_up:
if (is_powered_down) {
pm = 1;
x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
if (x) {
pr_warn("unable to force dcon to power up: %d!\n", x);
return x;
}
usleep_range(10000, 11000); /* we'll be conservative */
}
pdata->bus_stabilize_wiggle();
for (x = -1, timeout = 50; timeout && x < 0; timeout--) {
usleep_range(1000, 1100);
x = dcon_read(dcon, DCON_REG_ID);
}
if (x < 0) {
pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n");
BUG_ON(olpc_board_at_least(olpc_board(0xc2)));
pm = 0;
olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
msleep(100);
is_powered_down = 1;
goto power_up; /* argh, stupid hardware.. */
}
if (is_powered_down)
return dcon_hw_init(dcon, 0);
return 0;
}
static void dcon_set_backlight(struct dcon_priv *dcon, u8 level)
{
dcon->bl_val = level;
dcon_write(dcon, DCON_REG_BRIGHT, dcon->bl_val);
/* Purposely turn off the backlight when we go to level 0 */
if (dcon->bl_val == 0) {
dcon->disp_mode &= ~MODE_BL_ENABLE;
dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
} else if (!(dcon->disp_mode & MODE_BL_ENABLE)) {
dcon->disp_mode |= MODE_BL_ENABLE;
dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
}
}
/* Set the output type to either color or mono */
static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono)
{
if (dcon->mono == enable_mono)
return 0;
dcon->mono = enable_mono;
if (enable_mono) {
dcon->disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA);
dcon->disp_mode |= MODE_MONO_LUMA;
} else {
dcon->disp_mode &= ~(MODE_MONO_LUMA);
dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA;
}
dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
return 0;
}
/* For now, this will be really stupid - we need to address how
* DCONLOAD works in a sleep and account for it accordingly
*/
static void dcon_sleep(struct dcon_priv *dcon, bool sleep)
{
int x;
/* Turn off the backlight and put the DCON to sleep */
if (dcon->asleep == sleep)
return;
if (!olpc_board_at_least(olpc_board(0xc2)))
return;
if (sleep) {
u8 pm = 0;
x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
if (x)
pr_warn("unable to force dcon to power down: %d!\n", x);
else
dcon->asleep = sleep;
} else {
/* Only re-enable the backlight if the backlight value is set */
if (dcon->bl_val != 0)
dcon->disp_mode |= MODE_BL_ENABLE;
x = dcon_bus_stabilize(dcon, 1);
if (x)
pr_warn("unable to reinit dcon hardware: %d!\n", x);
else
dcon->asleep = sleep;
/* Restore backlight */
dcon_set_backlight(dcon, dcon->bl_val);
}
/* We should turn off some stuff in the framebuffer - but what? */
}
/* the DCON seems to get confused if we change DCONLOAD too
* frequently -- i.e., approximately faster than frame time.
* normally we don't change it this fast, so in general we won't
* delay here.
*/
static void dcon_load_holdoff(struct dcon_priv *dcon)
{
ktime_t delta_t, now;
while (1) {
now = ktime_get();
delta_t = ktime_sub(now, dcon->load_time);
if (ktime_to_ns(delta_t) > NSEC_PER_MSEC * 20)
break;
mdelay(4);
}
}
static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank)
{
int err;
console_lock();
if (!lock_fb_info(dcon->fbinfo)) {
console_unlock();
dev_err(&dcon->client->dev, "unable to lock framebuffer\n");
return false;
}
dcon->ignore_fb_events = true;
err = fb_blank(dcon->fbinfo,
blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
dcon->ignore_fb_events = false;
unlock_fb_info(dcon->fbinfo);
console_unlock();
if (err) {
dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n",
blank ? "" : "un");
return false;
}
return true;
}
/* Set the source of the display (CPU or DCON) */
static void dcon_source_switch(struct work_struct *work)
{
struct dcon_priv *dcon = container_of(work, struct dcon_priv,
switch_source);
int source = dcon->pending_src;
if (dcon->curr_src == source)
return;
dcon_load_holdoff(dcon);
dcon->switched = false;
switch (source) {
case DCON_SOURCE_CPU:
pr_info("dcon_source_switch to CPU\n");
/* Enable the scanline interrupt bit */
if (dcon_write(dcon, DCON_REG_MODE,
dcon->disp_mode | MODE_SCAN_INT))
pr_err("couldn't enable scanline interrupt!\n");
else
/* Wait up to one second for the scanline interrupt */
wait_event_timeout(dcon->waitq, dcon->switched, HZ);
if (!dcon->switched)
pr_err("Timeout entering CPU mode; expect a screen glitch.\n");
/* Turn off the scanline interrupt */
if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode))
pr_err("couldn't disable scanline interrupt!\n");
/*
* Ideally we'd like to disable interrupts here so that the
* fb unblanking and DCON turn on happen at a known time value;
* however, we can't do that right now with fb_blank
* messing with semaphores.
*
* For now, we just hope..
*/
if (!dcon_blank_fb(dcon, false)) {
pr_err("Failed to enter CPU mode\n");
dcon->pending_src = DCON_SOURCE_DCON;
return;
}
/* And turn off the DCON */
pdata->set_dconload(1);
dcon->load_time = ktime_get();
pr_info("The CPU has control\n");
break;
case DCON_SOURCE_DCON:
{
ktime_t delta_t;