Commit b87fc3e6 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull staging fixes from Greg Kroah-Hartman:
 "Here are a number of small fixes to staging drivers for your 3.8-rc3
  tree.

  Well, the omapdrm fixes aren't really "small" but they were waiting on
  a number of other drm patches to go in through the drm tree, and got
  delayed by my vacation over the holidays.  They are totally
  self-contained, everyone involved have acked them, and they fix issues
  that people have been having with the driver.

  Other than that one, it's a bunch of tiny bugfixes for a number of
  reported issues.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

* tag 'staging-3.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (36 commits)
  staging: zram: fix invalid memory references during disk write
  staging: tidspbridge: use prepare/unprepare on dsp clocks
  staging: tidspbridge: Fix build breakage due to splitting CM functions.
  staging: comedi: comedi_test: fix race when cancelling command
  staging: comedi: Kconfig: COMEDI_NI_AT_A2150 should select COMEDI_FC
  staging: comedi: prevent auto-unconfig of manually configured devices
  staging: comedi: fix minimum AO period for NI 625x and NI 628x
  staging: vme_pio2: fix oops on module unloading
  staging: speakup: avoid out-of-range access in synth_add()
  staging: speakup: avoid out-of-range access in synth_init()
  staging: rtl8192e: Fix failure to check pci_map_single()
  staging: rtl8187se: Fix failure to check pci_map_single()
  staging: drm/imx: fix double free bug in error path
  staging: drm/imx: several bug fixes
  staging: drm/imx: check return value of ipu_reset()
  staging: drm/omap: fix flags in dma buf exporting
  staging: drm/omap: use omapdss low level API
  staging/fwserial: Update TODO file per reviewer comments
  staging/fwserial: Limit tx/rx to 1394-2008 spec maximum
  staging/fwserial: Refine Kconfig help text
  ...
parents 46fed0a5 397c6066
......@@ -8,6 +8,7 @@ config HID_SENSOR_ACCEL_3D
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID Accelerometers 3D"
help
Say yes here to build support for the HID SENSOR
......
......@@ -411,7 +411,11 @@ static int ad7266_probe(struct spi_device *spi)
if (ret)
goto error_put_reg;
st->vref_uv = regulator_get_voltage(st->reg);
ret = regulator_get_voltage(st->reg);
if (ret < 0)
goto error_disable_reg;
st->vref_uv = ret;
} else {
/* Use internal reference */
st->vref_uv = 2500000;
......
......@@ -80,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
*timestamp = pf->timestamp;
}
iio_push_to_buffers(indio_dev, (u8 *)st->buffer);
iio_push_to_buffers(idev, (u8 *)st->buffer);
iio_trigger_notify_done(idev->trig);
......
......@@ -1605,6 +1605,7 @@ static int max1363_probe(struct i2c_client *client,
return 0;
error_free_irq:
if (client->irq)
free_irq(st->client->irq, indio_dev);
error_uninit_buffer:
iio_buffer_unregister(indio_dev);
......@@ -1612,12 +1613,12 @@ static int max1363_probe(struct i2c_client *client,
max1363_buffer_cleanup(indio_dev);
error_free_available_scan_masks:
kfree(indio_dev->available_scan_masks);
error_unregister_map:
iio_map_array_unregister(indio_dev, client->dev.platform_data);
error_disable_reg:
regulator_disable(st->reg);
error_put_reg:
regulator_put(st->reg);
error_unregister_map:
iio_map_array_unregister(indio_dev, client->dev.platform_data);
error_free_device:
iio_device_free(indio_dev);
error_out:
......@@ -1635,10 +1636,8 @@ static int max1363_remove(struct i2c_client *client)
iio_buffer_unregister(indio_dev);
max1363_buffer_cleanup(indio_dev);
kfree(indio_dev->available_scan_masks);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
iio_map_array_unregister(indio_dev, client->dev.platform_data);
iio_device_free(indio_dev);
......
......@@ -6,7 +6,7 @@ menu "Hid Sensor IIO Common"
config HID_SENSOR_IIO_COMMON
tristate "Common modules for all HID Sensor IIO drivers"
depends on HID_SENSOR_HUB
select IIO_TRIGGER if IIO_BUFFER
select HID_SENSOR_IIO_TRIGGER if IIO_BUFFER
help
Say yes here to build support for HID sensor to use
HID sensor common processing for attributes and IIO triggers.
......@@ -14,6 +14,17 @@ config HID_SENSOR_IIO_COMMON
HID sensor drivers, this module contains processing for those
attributes.
config HID_SENSOR_IIO_TRIGGER
tristate "Common module (trigger) for all HID Sensor IIO drivers"
depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON
select IIO_TRIGGER
help
Say yes here to build trigger support for HID sensors.
Triggers will be send if all requested attributes were read.
If this driver is compiled as a module, it will be named
hid-sensor-trigger.
config HID_SENSOR_ENUM_BASE_QUIRKS
bool "ENUM base quirks for HID Sensor IIO drivers"
depends on HID_SENSOR_IIO_COMMON
......
......@@ -3,4 +3,5 @@
#
obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o
hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o
obj-$(CONFIG_HID_SENSOR_IIO_TRIGGER) += hid-sensor-trigger.o
hid-sensor-iio-common-y := hid-sensor-attributes.o
......@@ -406,7 +406,11 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
goto error_free_reg;
}
st->vref = regulator_get_voltage(st->vref_reg);
ret = regulator_get_voltage(st->vref_reg);
if (ret < 0)
goto error_disable_reg;
st->vref = ret;
} else {
st->vref = st->chip_info->int_vref;
ctrl |= AD5380_CTRL_INT_VREF_EN;
......
......@@ -226,7 +226,11 @@ static int ad5446_probe(struct device *dev, const char *name,
if (ret)
goto error_put_reg;
voltage_uv = regulator_get_voltage(reg);
ret = regulator_get_voltage(reg);
if (ret < 0)
goto error_disable_reg;
voltage_uv = ret;
}
indio_dev = iio_device_alloc(sizeof(*st));
......
......@@ -296,7 +296,11 @@ static int ad5504_probe(struct spi_device *spi)
if (ret)
goto error_put_reg;
voltage_uv = regulator_get_voltage(reg);
ret = regulator_get_voltage(reg);
if (ret < 0)
goto error_disable_reg;
voltage_uv = ret;
}
spi_set_drvdata(spi, indio_dev);
......
......@@ -238,7 +238,11 @@ static int ad5624r_probe(struct spi_device *spi)
if (ret)
goto error_put_reg;
voltage_uv = regulator_get_voltage(st->reg);
ret = regulator_get_voltage(st->reg);
if (ret < 0)
goto error_disable_reg;
voltage_uv = ret;
}
spi_set_drvdata(spi, indio_dev);
......
......@@ -332,7 +332,11 @@ static int ad5686_probe(struct spi_device *spi)
if (ret)
goto error_put_reg;
voltage_uv = regulator_get_voltage(st->reg);
ret = regulator_get_voltage(st->reg);
if (ret < 0)
goto error_disable_reg;
voltage_uv = ret;
}
st->chip_info =
......
......@@ -365,7 +365,11 @@ static int ad5791_probe(struct spi_device *spi)
if (ret)
goto error_put_reg_pos;
pos_voltage_uv = regulator_get_voltage(st->reg_vdd);
ret = regulator_get_voltage(st->reg_vdd);
if (ret < 0)
goto error_disable_reg_pos;
pos_voltage_uv = ret;
}
st->reg_vss = regulator_get(&spi->dev, "vss");
......@@ -374,7 +378,11 @@ static int ad5791_probe(struct spi_device *spi)
if (ret)
goto error_put_reg_neg;
neg_voltage_uv = regulator_get_voltage(st->reg_vss);
ret = regulator_get_voltage(st->reg_vss);
if (ret < 0)
goto error_disable_reg_neg;
neg_voltage_uv = ret;
}
st->pwr_down = true;
......@@ -428,6 +436,7 @@ static int ad5791_probe(struct spi_device *spi)
if (!IS_ERR(st->reg_vss))
regulator_put(st->reg_vss);
error_disable_reg_pos:
if (!IS_ERR(st->reg_vdd))
regulator_disable(st->reg_vdd);
error_put_reg_pos:
......
......@@ -173,7 +173,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
} while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt);
} while (r_cnt == 0);
tmp = freq * (u64)st->r1_mod + (st->fpfd > 1);
tmp = freq * (u64)st->r1_mod + (st->fpfd >> 1);
do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */
st->r0_fract = do_div(tmp, st->r1_mod);
st->r0_int = tmp;
......
......@@ -17,6 +17,7 @@ config HID_SENSOR_GYRO_3D
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID Gyroscope 3D"
help
Say yes here to build support for the HID SENSOR
......
......@@ -47,6 +47,7 @@ config HID_SENSOR_ALS
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID ALS"
help
Say yes here to build support for the HID SENSOR
......
......@@ -8,6 +8,7 @@ config HID_SENSOR_MAGNETOMETER_3D
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID Magenetometer 3D"
help
Say yes here to build support for the HID SENSOR
......
......@@ -444,6 +444,7 @@ config COMEDI_ADQ12B
config COMEDI_NI_AT_A2150
tristate "NI AT-A2150 ISA card support"
select COMEDI_FC
depends on VIRT_TO_BUS
---help---
Enable support for National Instruments AT-A2150 cards
......
......@@ -1549,6 +1549,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
if (cmd == COMEDI_DEVCONFIG) {
rc = do_devconfig_ioctl(dev,
(struct comedi_devconfig __user *)arg);
if (rc == 0)
/* Evade comedi_auto_unconfig(). */
dev_file_info->hardware_device = NULL;
goto done;
}
......
......@@ -345,7 +345,7 @@ static int waveform_ai_cancel(struct comedi_device *dev,
struct waveform_private *devpriv = dev->private;
devpriv->timer_running = 0;
del_timer(&devpriv->timer);
del_timer_sync(&devpriv->timer);
return 0;
}
......
......@@ -963,7 +963,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
.ao_speed = 357,
.ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
......@@ -982,7 +982,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
.ao_speed = 357,
.ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
......@@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
.ao_speed = 357,
.ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
......@@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
.ao_speed = 357,
.ao_speed = 350,
.num_p0_dio_channels = 32,
.caldac = {caldac_none},
.has_8255 = 0,
......@@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_625x_ao,
.reg_type = ni_reg_625x,
.ao_unipolar = 0,
.ao_speed = 357,
.ao_speed = 350,
.num_p0_dio_channels = 32,
.caldac = {caldac_none},
.has_8255 = 0,
......@@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_628x_ao,
.reg_type = ni_reg_628x,
.ao_unipolar = 1,
.ao_speed = 357,
.ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
......@@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_628x_ao,
.reg_type = ni_reg_628x,
.ao_unipolar = 1,
.ao_speed = 357,
.ao_speed = 350,
.num_p0_dio_channels = 8,
.caldac = {caldac_none},
.has_8255 = 0,
......@@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_boards[] = {
.ao_range_table = &range_ni_M_628x_ao,
.reg_type = ni_reg_628x,
.ao_unipolar = 1,
.ao_speed = 357,
.ao_speed = 350,
.num_p0_dio_channels = 32,
.caldac = {caldac_none},
.has_8255 = 0,
......
......@@ -3,7 +3,9 @@ config FIREWIRE_SERIAL
depends on FIREWIRE
help
This enables TTY over IEEE 1394, providing high-speed serial
connectivity to cabled peers.
connectivity to cabled peers. This driver implements a
ad-hoc transport protocol and is currently limited to
Linux-to-Linux communication.
To compile this driver as a module, say M here: the module will
be called firewire-serial.
TODOs
-----
TODOs prior to this driver moving out of staging
------------------------------------------------
1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR
- I/O is handled asynchronously which presents some issues when error
conditions occur.
......@@ -11,17 +11,9 @@ TODOs
-- Issues with firewire stack --
1. This driver uses the same unregistered vendor id that the firewire core does
(0xd00d1e). Perhaps this could be exposed as a define in
firewire-constants.h?
2. MAX_ASYNC_PAYLOAD needs to be publicly exposed by core/ohci
- otherwise how will this driver know the max size of address window to
open for one packet write?
firewire.h?
3. Maybe device_max_receive() and link_speed_to_max_payload() should be
taken up by the firewire core?
4. To avoid dropping rx data while still limiting the maximum buffering,
the size of the AR context must be known. How to expose this to drivers?
5. Explore if bigger AR context will reduce RCODE_BUSY responses
(or auto-grow to certain max size -- but this would require major surgery
as the current AR is contiguously mapped)
-- Issues with TTY core --
1. Hack for alternate device name scheme
......
......@@ -179,7 +179,7 @@ static void dump_profile(struct seq_file *m, struct stats *stats)
/* Returns the max receive packet size for the given card */
static inline int device_max_receive(struct fw_device *fw_device)
{
return 1 << (clamp_t(int, fw_device->max_rec, 8U, 13U) + 1);
return 1 << (clamp_t(int, fw_device->max_rec, 8U, 11U) + 1);
}
static void fwtty_log_tx_error(struct fwtty_port *port, int rcode)
......
......@@ -374,10 +374,10 @@ static inline void fwtty_bind_console(struct fwtty_port *port,
*/
static inline int link_speed_to_max_payload(unsigned speed)
{
static const int max_async[] = { 307, 614, 1229, 2458, 4916, 9832, };
BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_3200);
static const int max_async[] = { 307, 614, 1229, 2458, };
BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_800);
speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_3200);
speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_800);
if (limit_bw)
return max_async[speed];
else
......
......@@ -27,8 +27,8 @@ config ADIS16130
config ADIS16260
tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
depends on SPI
select IIO_TRIGGER if IIO_BUFFER
select IIO_SW_RING if IIO_BUFFER
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices ADIS16260 ADIS16265
ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors.
......
......@@ -584,7 +584,6 @@ int imx_drm_add_encoder(struct drm_encoder *encoder,
ret = imx_drm_encoder_register(imx_drm_encoder);
if (ret) {
kfree(imx_drm_encoder);
ret = -ENOMEM;
goto err_register;
}
......
......@@ -1104,7 +1104,9 @@ static int ipu_probe(struct platform_device *pdev)
if (ret)
goto out_failed_irq;
ipu_reset(ipu);
ret = ipu_reset(ipu);
if (ret)
goto out_failed_reset;
/* Set MCU_T to divide MCU access window into 2 */
ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
......@@ -1129,6 +1131,7 @@ static int ipu_probe(struct platform_device *pdev)
ipu_submodules_exit(ipu);
failed_submodules_init:
ipu_irq_exit(ipu);
out_failed_reset:
out_failed_irq:
clk_disable_unprepare(ipu->clk);
failed_clk_get:
......
......@@ -452,7 +452,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
int ret;
ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]);
if (IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) {
if (IS_ERR(ipu_crtc->ipu_ch)) {
ret = PTR_ERR(ipu_crtc->ipu_ch);
goto err_out;
}
......@@ -472,7 +472,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
if (pdata->dp >= 0) {
ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp);
if (IS_ERR(ipu_crtc->dp)) {
ret = PTR_ERR(ipu_crtc->ipu_ch);
ret = PTR_ERR(ipu_crtc->dp);
goto err_out;
}
}
......@@ -548,6 +548,8 @@ static int ipu_drm_probe(struct platform_device *pdev)
ipu_crtc->dev = &pdev->dev;
ret = ipu_crtc_init(ipu_crtc, pdata);
if (ret)
return ret;
platform_set_drvdata(pdev, ipu_crtc);
......
......@@ -5,6 +5,7 @@
ccflags-y := -Iinclude/drm -Werror
omapdrm-y := omap_drv.o \
omap_irq.o \
omap_debugfs.o \
omap_crtc.o \
omap_plane.o \
......
......@@ -17,9 +17,6 @@ TODO
. Revisit GEM sync object infrastructure.. TTM has some framework for this
already. Possibly this could be refactored out and made more common?
There should be some way to do this with less wheel-reinvention.
. Review DSS vs KMS mismatches. The omap_dss_device is sort of part encoder,
part connector. Which results in a bit of duct tape to fwd calls from
encoder to connector. Possibly this could be done a bit better.
. Solve PM sequencing on resume. DMM/TILER must be reloaded before any
access is made from any component in the system. Which means on suspend
CRTC's should be disabled, and on resume the LUT should be reprogrammed
......
......@@ -31,9 +31,10 @@
struct omap_connector {
struct drm_connector base;
struct omap_dss_device *dssdev;
struct drm_encoder *encoder;
};
static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
void copy_timings_omap_to_drm(struct drm_display_mode *mode,
struct omap_video_timings *timings)
{
mode->clock = timings->pixel_clock;
......@@ -64,7 +65,7 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
mode->flags |= DRM_MODE_FLAG_NVSYNC;
}
static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
void copy_timings_drm_to_omap(struct omap_video_timings *timings,
struct drm_display_mode *mode)
{
timings->pixel_clock = mode->clock;
......@@ -96,48 +97,7 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
}
static void omap_connector_dpms(struct drm_connector *connector, int mode)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev = omap_connector->dssdev;
int old_dpms;
DBG("%s: %d", dssdev->name, mode);
old_dpms = connector->dpms;
/* from off to on, do from crtc to connector */
if (mode < old_dpms)
drm_helper_connector_dpms(connector, mode);
if (mode == DRM_MODE_DPMS_ON) {
/* store resume info for suspended displays */
switch (dssdev->state) {
case OMAP_DSS_DISPLAY_SUSPENDED:
dssdev->activate_after_resume = true;
break;
case OMAP_DSS_DISPLAY_DISABLED: {
int ret = dssdev->driver->enable(dssdev);
if (ret) {
DBG("%s: failed to enable: %d",
dssdev->name, ret);
dssdev->driver->disable(dssdev);
}
break;
}
default:
break;
}
} else {
/* TODO */
}
/* from on to off, do from connector to crtc */
if (mode > old_dpms)
drm_helper_connector_dpms(connector, mode);
}
enum drm_connector_status omap_connector_detect(
static enum drm_connector_status omap_connector_detect(
struct drm_connector *connector, bool force)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
......@@ -164,8 +124,6 @@ static void omap_connector_destroy(struct drm_connector *connector)
struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev = omap_connector->dssdev;
dssdev->driver->disable(dssdev);
DBG("%s", omap_connector->dssdev->name);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
......@@ -261,36 +219,12 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
struct drm_encoder *omap_connector_attached_encoder(
struct drm_connector *connector)
{
int i;
struct omap_connector *omap_connector = to_omap_connector(connector);
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
struct drm_mode_object *obj;
if (connector->encoder_ids[i] == 0)
break;
obj = drm_mode_object_find(connector->dev,
connector->encoder_ids[i],
DRM_MODE_OBJECT_ENCODER);
if (obj) {
struct drm_encoder *encoder = obj_to_encoder(obj);
struct omap_overlay_manager *mgr =
omap_encoder_get_manager(encoder);
DBG("%s: found %s", omap_connector->dssdev->name,
mgr->name);
return encoder;
}
}
DBG("%s: no encoder", omap_connector->dssdev->name);
return NULL;
return omap_connector->encoder;
}
static const struct drm_connector_funcs omap_connector_funcs = {
.dpms = omap_connector_dpms,
.dpms = drm_helper_connector_dpms,
.detect = omap_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = omap_connector_destroy,
......@@ -302,34 +236,6 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
.best_encoder = omap_connector_attached_encoder,
};
/* called from encoder when mode is set, to propagate settings to the dssdev */
void omap_connector_mode_set(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct drm_device *dev = connector->dev;
struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev = omap_connector->dssdev;
struct omap_dss_driver *dssdrv = dssdev->driver;
struct omap_video_timings timings = {0};
copy_timings_drm_to_omap(&timings, mode);
DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
omap_connector->dssdev->name,
mode->base.id, mode->name, mode->vrefresh, mode->clock,
mode->hdisplay, mode->hsync_start,
mode->hsync_end, mode->htotal,
mode->vdisplay, mode->vsync_start,
mode->vsync_end, mode->vtotal, mode->type, mode->flags);
if (dssdrv->check_timings(dssdev, &timings)) {
dev_err(dev->dev, "could not set timings\n");
return;
}
dssdrv->set_timings(dssdev, &timings);
}
/* flush an area of the framebuffer (in case of manual update display that
* is not automatically flushed)
*/
......@@ -344,7 +250,8 @@ void omap_connector_flush(struct drm_connector *connector,
/* initialize connector */
struct drm_connector *omap_connector_init(struct drm_device *dev,
int connector_type, struct omap_dss_device *dssdev)
int connector_type, struct omap_dss_device *dssdev,
struct drm_encoder *encoder)
{
struct drm_connector *connector = NULL;
struct omap_connector *omap_connector;
......@@ -360,6 +267,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
}
omap_connector->dssdev = dssdev;
omap_connector->encoder = encoder;
connector = &omap_connector->base;
drm_connector_init(dev, connector, &omap_connector_funcs,
......
This diff is collapsed.
This diff is collapsed.
......@@ -28,6 +28,7 @@
#include <linux/platform_data/omap_drm.h>
#include "omap_drm.h"
#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */
......@@ -39,6 +40,51 @@
*/
#define MAX_MAPPERS 2
/* parameters which describe (unrotated) coordinates of scanout within a fb: */
struct omap_drm_window {
uint32_t rotation;
int32_t crtc_x, crtc_y; /* signed because can be offscreen */
uint32_t crtc_w, crtc_h;
uint32_t src_x, src_y;
uint32_t src_w, src_h;
};
/* Once GO bit is set, we can't make further updates to shadowed registers
* until the GO bit is cleared. So various parts in the kms code that need
* to update shadowed registers queue up a pair of callbacks, pre_apply
* which is called before setting GO bit, and post_apply that is called
* after GO bit is cleared. The crtc manages the queuing, and everyone
* else goes thru omap_crtc_apply() using these callbacks so that the
* code which has to deal w/ GO bit state is centralized.
*/
struct omap_drm_apply {
struct list_head pending_node, queued_node;
bool queued;
void (*pre_apply)(struct omap_drm_apply *apply);
void (*post_apply)(struct omap_drm_apply *apply);
};
/* For transiently registering for different DSS irqs that various parts
* of the KMS code need during setup/configuration. We these are not
* necessarily the same as what drm_vblank_get/put() are requesting, and
* the hysteresis in drm_vblank_put() is not necessarily desirable for
* internal housekeeping related irq usage.
*/
struct omap_drm_irq {
struct list_head node;
uint32_t irqmask;
bool registered;
void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus);
};
/* For KMS code that needs to wait for a certain # of IRQs:
*/
struct omap_irq_wait;
struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
uint32_t irqmask, int count);
int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
unsigned long timeout);
struct omap_drm_private {
uint32_t omaprev;
......@@ -58,6 +104,7 @@ struct omap_drm_private {
struct workqueue_struct *wq;
/* list of GEM objects: */
struct list_head obj_list;
bool has_dmm;
......@@ -65,6 +112,11 @@ struct omap_drm_private {
/* properties: */
struct drm_property *rotation_prop;
struct drm_property *zorder_prop;
/* irq handling: */
struct list_head irq_list; /* list of omap_drm_irq */
uint32_t vblank_mask; /* irq bits set for userspace vblank */
struct omap_drm_irq error_handler;
};
/* this should probably be in drm-core to standardize amongst drivers */
......@@ -75,15 +127,6 @@ struct omap_drm_private {
#define DRM_REFLECT_X 4
#define DRM_REFLECT_Y 5
/* parameters which describe (unrotated) coordinates of scanout within a fb: */
struct omap_drm_window {
uint32_t rotation;
int32_t crtc_x, crtc_y; /* signed because can be offscreen */
uint32_t crtc_w, crtc_h;
uint32_t src_x, src_y;
uint32_t src_w, src_h;
};
#ifdef CONFIG_DEBUG_FS
int omap_debugfs_init(struct drm_minor *minor);
void omap_debugfs_cleanup(struct drm_minor *minor);
......@@ -92,23 +135,36 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
#endif
int omap_irq_enable_vblank(struct drm_device *dev, int crtc);
void omap_irq_disable_vblank(struct drm_device *dev, int crtc);
irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
void omap_irq_preinstall(struct drm_device *dev);
int omap_irq_postinstall(struct drm_device *dev);
void omap_irq_uninstall(struct drm_device *dev);
void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
int omap_drm_irq_uninstall(struct drm_device *dev);
int omap_drm_irq_install(struct drm_device *dev);
struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
void omap_fbdev_free(struct drm_device *dev);
const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc);
enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
int omap_crtc_apply(struct drm_crtc *crtc,
struct omap_drm_apply *apply);
struct drm_crtc *omap_crtc_init(struct drm_device *dev,
struct omap_overlay *ovl, int id);
struct drm_plane *plane, enum omap_channel channel, int id);
struct drm_plane *omap_plane_init(struct drm_device *dev,
struct omap_overlay *ovl, unsigned int possible_crtcs,
bool priv);
int plane_id, bool private_plane);
int omap_plane_dpms(struct drm_plane *plane, int mode);
int omap_plane_mode_set(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
void omap_plane_on_endwin(struct drm_plane *plane,
uint32_t src_w, uint32_t src_h,
void (*fxn)(void *), void *arg);
void omap_plane_install_properties(struct drm_plane *plane,
struct drm_mode_object *obj);
......@@ -116,21 +172,25 @@ int omap_plane_set_property(struct drm_plane *plane,
struct drm_property *property, uint64_t val);
struct drm_encoder *omap_encoder_init(struct drm_device *dev,
struct omap_overlay_manager *mgr);
struct omap_overlay_manager *omap_encoder_get_manager(
struct omap_dss_device *dssdev);
int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled);
int omap_encoder_update(struct drm_encoder *encoder,
struct omap_overlay_manager *mgr,
struct omap_video_timings *timings);
struct drm_connector *omap_connector_init(struct drm_device *dev,
int connector_type, struct omap_dss_device *dssdev,
struct drm_encoder *encoder);
struct drm_encoder *omap_connector_attached_encoder(
struct drm_connector *connector);
enum drm_connector_status omap_connector_detect(
struct drm_connector *connector, bool force);
struct drm_connector *omap_connector_init(struct drm_device *dev,
int connector_type, struct omap_dss_device *dssdev);
void omap_connector_mode_set(struct drm_connector *connector,
struct drm_display_mode *mode);
void omap_connector_flush(struct drm_connector *connector,
int x, int y, int w, int h);
void copy_timings_omap_to_drm(struct drm_display_mode *mode,
struct omap_video_timings *timings);
void copy_timings_drm_to_omap(struct omap_video_timings *timings,
struct drm_display_mode *mode);
uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
uint32_t max_formats, enum omap_color_mode supported_modes);
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
......@@ -207,6 +267,40 @@ static inline int align_pitch(int pitch, int width, int bpp)
return ALIGN(pitch, 8 * bytespp);
}
static inline enum omap_channel pipe2chan(int pipe)
{
int num_mgrs = dss_feat_get_num_mgrs();
/*
* We usually don't want to create a CRTC for each manager,
* at least not until we have a way to expose private planes
* to userspace. Otherwise there would not be enough video
* pipes left for drm planes. The higher #'d managers tend
* to have more features so start in reverse order.
*/
return num_mgrs - pipe - 1;
}
/* map crtc to vblank mask */
static inline uint32_t pipe2vbl(int crtc)
{
enum omap_channel channel = pipe2chan(crtc);
return dispc_mgr_get_vsync_irq(channel);
}
static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc)
{
struct omap_drm_private *priv = dev->dev_private;
int i;
for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++)
if (priv->crtcs[i] == crtc)
return i;
BUG(); /* bogus CRTC ptr */
return -1;
}
/* should these be made into common util helpers?
*/
......
......@@ -22,37 +22,56 @@
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
#include <linux/list.h>
/*
* encoder funcs
*/
#define to_omap_encoder(x) container_of(x, struct omap_encoder, base)
/* The encoder and connector both map to same dssdev.. the encoder
* handles the 'active' parts, ie. anything the modifies the state
* of the hw, and the connector handles the 'read-only' parts, like
* detecting connection and reading edid.
*/
struct omap_encoder {
struct drm_encoder base;
struct omap_overlay_manager *mgr;
struct omap_dss_device *dssdev;
};
static void omap_encoder_destroy(struct drm_encoder *encoder)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
DBG("%s", omap_encoder->mgr->name);
drm_encoder_cleanup(encoder);
kfree(omap_encoder);
}
static const struct drm_encoder_funcs omap_encoder_funcs = {
.destroy = omap_encoder_destroy,
};
/*
* The CRTC drm_crtc_helper_set_mode() doesn't really give us the right
* order.. the easiest way to work around this for now is to make all
* the encoder-helper's no-op's and have the omap_crtc code take care
* of the sequencing and call us in the right points.
*
* Eventually to handle connecting CRTCs to different encoders properly,
* either the CRTC helpers need to change or we need to replace
* drm_crtc_helper_set_mode(), but lets wait until atomic-modeset for
* that.
*/
static void omap_encoder_dpms(struct drm_encoder *encoder, int mode)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
DBG("%s: %d", omap_encoder->mgr->name, mode);
}
static bool omap_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
DBG("%s", omap_encoder->mgr->name);
return true;
}
......@@ -60,47 +79,16 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct drm_device *dev = encoder->dev;
struct omap_drm_private *priv = dev->dev_private;
int i;
mode = adjusted_mode;
DBG("%s: set mode: %dx%d", omap_encoder->mgr->name,
mode->hdisplay, mode->vdisplay);
for (i = 0; i < priv->num_connectors; i++) {
struct drm_connector *connector = priv->connectors[i];
if (connector->encoder == encoder)
omap_connector_mode_set(connector, mode);
}
}
static void omap_encoder_prepare(struct drm_encoder *encoder)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct drm_encoder_helper_funcs *encoder_funcs =
encoder->helper_private;
DBG("%s", omap_encoder->mgr->name);
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
}
static void omap_encoder_commit(struct drm_encoder *encoder)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct drm_encoder_helper_funcs *encoder_funcs =
encoder->helper_private;
DBG("%s", omap_encoder->mgr->name);
omap_encoder->mgr->apply(omap_encoder->mgr);
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
}
static const struct drm_encoder_funcs omap_encoder_funcs = {
.destroy = omap_encoder_destroy,
};
static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
.dpms = omap_encoder_dpms,
.mode_fixup = omap_encoder_mode_fixup,
......@@ -109,23 +97,54 @@ static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
.commit = omap_encoder_commit,
};
struct omap_overlay_manager *omap_encoder_get_manager(
struct drm_encoder *encoder)
/*
* Instead of relying on the helpers for modeset, the omap_crtc code
* calls these functions in the proper sequence.
*/
int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
return omap_encoder->mgr;
struct omap_dss_device *dssdev = omap_encoder->dssdev;
struct omap_dss_driver *dssdrv = dssdev->driver;
if (enabled) {
return dssdrv->enable(dssdev);
} else {
dssdrv->disable(dssdev);
return 0;
}
}
int omap_encoder_update(struct drm_encoder *encoder,
struct omap_overlay_manager *mgr,
struct omap_video_timings *timings)
{
struct drm_device *dev = encoder->dev;
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct omap_dss_device *dssdev = omap_encoder->dssdev;
struct omap_dss_driver *dssdrv = dssdev->driver;
int ret;
dssdev->output->manager = mgr;
ret = dssdrv->check_timings(dssdev, timings);
if (ret) {
dev_err(dev->dev, "could not set timings: %d\n", ret);
return ret;
}
dssdrv->set_timings(dssdev, timings);
return 0;
}
/* initialize encoder */
struct drm_encoder *omap_encoder_init(struct drm_device *dev,
struct omap_overlay_manager *mgr)
struct omap_dss_device *dssdev)
{
struct drm_encoder *encoder = NULL;
struct omap_encoder *omap_encoder;
struct omap_overlay_manager_info info;
int ret;
DBG("%s", mgr->name);
omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
if (!omap_encoder) {
......@@ -133,33 +152,14 @@ struct drm_encoder *omap_encoder_init(struct drm_device *dev,
goto fail;
}
omap_encoder->mgr = mgr;
omap_encoder->dssdev = dssdev;
encoder = &omap_encoder->base;
drm_encoder_init(dev, encoder, &omap_encoder_funcs,
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
mgr->get_manager_info(mgr, &info);
/* TODO: fix hard-coded setup.. */
info.default_color = 0x00000000;
info.trans_key = 0x00000000;
info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
info.trans_enabled = false;
ret = mgr->set_manager_info(mgr, &info);
if (ret) {
dev_err(dev->dev, "could not set manager info\n");
goto fail;
}
ret = mgr->apply(mgr);
if (ret) {
dev_err(dev->dev, "could not apply\n");
goto fail;
}
return encoder;
fail:
......
......@@ -194,7 +194,7 @@ struct dma_buf_ops omap_dmabuf_ops = {
struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *obj, int flags)
{
return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, 0600);
return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags);
}
struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
......
/*
* drivers/staging/omapdrm/omap_irq.c
*
* Copyright (C) 2012 Texas Instruments
* Author: Rob Clark <rob.clark@linaro.org>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "omap_drv.h"
static DEFINE_SPINLOCK(list_lock);
static void omap_irq_error_handler(struct omap_drm_irq *irq,
uint32_t irqstatus)
{
DRM_ERROR("errors: %08x\n", irqstatus);
}
/* call with list_lock and dispc runtime held */
static void omap_irq_update(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
struct omap_drm_irq *irq;
uint32_t irqmask = priv->vblank_mask;
BUG_ON(!spin_is_locked(&list_lock));
list_for_each_entry(irq, &priv->irq_list, node)
irqmask |= irq->irqmask;
DBG("irqmask=%08x", irqmask);
dispc_write_irqenable(irqmask);
dispc_read_irqenable(); /* flush posted write */
}
void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
{
struct omap_drm_private *priv = dev->dev_private;
unsigned long flags;
dispc_runtime_get();
spin_lock_irqsave(&list_lock, flags);
if (!WARN_ON(irq->registered)) {
irq->registered = true;
list_add(&irq->node, &priv->irq_list);
omap_irq_update(dev);
}
spin_unlock_irqrestore(&list_lock, flags);
dispc_runtime_put();
}
void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
{
unsigned long flags;
dispc_runtime_get();
spin_lock_irqsave(&list_lock, flags);
if (!WARN_ON(!irq->registered)) {
irq->registered = false;
list_del(&irq->node);
omap_irq_update(dev);
}
spin_unlock_irqrestore(&list_lock, flags);
dispc_runtime_put();
}
struct omap_irq_wait {
struct omap_drm_irq irq;
int count;
};
static DECLARE_WAIT_QUEUE_HEAD(wait_event);
static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
{
struct omap_irq_wait *wait =
container_of(irq, struct omap_irq_wait, irq);
wait->count--;
wake_up_all(&wait_event);
}
struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
uint32_t irqmask, int count)
{
struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
wait->irq.irq = wait_irq;
wait->irq.irqmask = irqmask;
wait->count = count;
omap_irq_register(dev, &wait->irq);
return wait;
}
int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
unsigned long timeout)
{
int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
omap_irq_unregister(dev, &wait->irq);
kfree(wait);
if (ret == 0)
return -1;
return 0;
}
/**
* enable_vblank - enable vblank interrupt events
* @dev: DRM device
* @crtc: which irq to enable
*
* Enable vblank interrupts for @crtc. If the device doesn't have
* a hardware vblank counter, this routine should be a no-op, since
* interrupts will have to stay on to keep the count accurate.
*
* RETURNS
* Zero on success, appropriate errno if the given @crtc's vblank
* interrupt cannot be enabled.
*/
int omap_irq_enable_vblank(struct drm_device *dev, int crtc)
{
struct omap_drm_private *priv = dev->dev_private;
unsigned long flags;
DBG("dev=%p, crtc=%d", dev, crtc);
dispc_runtime_get();
spin_lock_irqsave(&list_lock, flags);
priv->vblank_mask |= pipe2vbl(crtc);
omap_irq_update(dev);
spin_unlock_irqrestore(&list_lock, flags);
dispc_runtime_put();
return 0;
}
/**
* disable_vblank - disable vblank interrupt events
* @dev: DRM device
* @crtc: which irq to enable
*
* Disable vblank interrupts for @crtc. If the device doesn't have
* a hardware vblank counter, this routine should be a no-op, since
* interrupts will have to stay on to keep the count accurate.
*/
void omap_irq_disable_vblank(struct drm_device *dev, int crtc)
{
struct omap_drm_private *priv = dev->dev_private;
unsigned long flags;
DBG("dev=%p, crtc=%d", dev, crtc);
dispc_runtime_get();
spin_lock_irqsave(&list_lock, flags);
priv->vblank_mask &= ~pipe2vbl(crtc);
omap_irq_update(dev);
spin_unlock_irqrestore(&list_lock, flags);
dispc_runtime_put();
}
irqreturn_t omap_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
struct omap_drm_private *priv = dev->dev_private;
struct omap_drm_irq *handler, *n;
unsigned long flags;
unsigned int id;
u32 irqstatus;
irqstatus = dispc_read_irqstatus();
dispc_clear_irqstatus(irqstatus);
dispc_read_irqstatus(); /* flush posted write */
VERB("irqs: %08x", irqstatus);
for (id = 0; id < priv->num_crtcs; id++)
if (irqstatus & pipe2vbl(id))
drm_handle_vblank(dev, id);
spin_lock_irqsave(&list_lock, flags);
list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
if (handler->irqmask & irqstatus) {
spin_unlock_irqrestore(&list_lock, flags);
handler->irq(handler, handler->irqmask & irqstatus);
spin_lock_irqsave(&list_lock, flags);
}
}
spin_unlock_irqrestore(&list_lock, flags);
return IRQ_HANDLED;
}
void omap_irq_preinstall(struct drm_device *dev)
{
DBG("dev=%p", dev);
dispc_runtime_get();
dispc_clear_irqstatus(0xffffffff);
dispc_runtime_put();
}
int omap_irq_postinstall(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
struct omap_drm_irq *error_handler = &priv->error_handler;
DBG("dev=%p", dev);
INIT_LIST_HEAD(&priv->irq_list);
error_handler->irq = omap_irq_error_handler;
error_handler->irqmask = DISPC_IRQ_OCP_ERR;
/* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think
* we just need to ignore it while enabling tv-out
*/
error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
omap_irq_register(dev, error_handler);
return 0;
}
void omap_irq_uninstall(struct drm_device *dev)
{
DBG("dev=%p", dev);
// TODO prolly need to call drm_irq_uninstall() somewhere too
}
/*
* We need a special version, instead of just using drm_irq_install(),
* because we need to register the irq via omapdss. Once omapdss and
* omapdrm are merged together we can assign the dispc hwmod data to
* ourselves and drop these and just use drm_irq_{install,uninstall}()
*/
int omap_drm_irq_install(struct drm_device *dev)
{
int ret;
mutex_lock(&dev->struct_mutex);
if (dev->irq_enabled) {
mutex_unlock(&dev->struct_mutex);
return -EBUSY;
}
dev->irq_enabled = 1;
mutex_unlock(&dev->struct_mutex);
/* Before installing handler */
if (dev->driver->irq_preinstall)
dev->driver->irq_preinstall(dev);
ret = dispc_request_irq(dev->driver->irq_handler, dev);
if (ret < 0) {
mutex_lock(&dev->struct_mutex);
dev->irq_enabled = 0;
mutex_unlock(&dev->struct_mutex);
return ret;
}
/* After installing handler */
if (dev->driver->irq_postinstall)
ret = dev->driver->irq_postinstall(dev);
if (ret < 0) {
mutex_lock(&dev->struct_mutex);
dev->irq_enabled = 0;
mutex_unlock(&dev->struct_mutex);
dispc_free_irq(dev);
}
return ret;
}
int omap_drm_irq_uninstall(struct drm_device *dev)
{
unsigned long irqflags;
int irq_enabled, i;
mutex_lock(&dev->struct_mutex);
irq_enabled = dev->irq_enabled;
dev->irq_enabled = 0;
mutex_unlock(&dev->struct_mutex);
/*
* Wake up any waiters so they don't hang.
*/
if (dev->num_crtcs) {
spin_lock_irqsave(&dev->vbl_lock, irqflags);
for (i = 0; i < dev->num_crtcs; i++) {
DRM_WAKEUP(&dev->vbl_queue[i]);
dev->vblank_enabled[i] = 0;
dev->last_vblank[i] =
dev->driver->get_vblank_counter(dev, i);
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
}
if (!irq_enabled)
return -EINVAL;
if (dev->driver->irq_uninstall)
dev->driver->irq_uninstall(dev);
dispc_free_irq(dev);
return 0;
}
This diff is collapsed.
......@@ -937,7 +937,8 @@ short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8),
PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(pdev, dma_tmp))
return -1;
if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp,
&(priv->rxbufferhead))) {
DMESGE("Unable to allocate mem RX buf");
......
......@@ -1183,6 +1183,8 @@ void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
pTxFwInfo->TxRate,
cb_desc);
if (pci_dma_mapping_error(priv->pdev, mapping))
RT_TRACE(COMP_ERR, "DMA Mapping error\n");;
if (cb_desc->bAMPDUEnable) {
pTxFwInfo->AllowAggregation = 1;
pTxFwInfo->RxMF = cb_desc->ampdu_factor;
......@@ -1280,6 +1282,8 @@ void rtl8192_tx_fill_cmd_desc(struct net_device *dev,
dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(priv->pdev, mapping))
RT_TRACE(COMP_ERR, "DMA Mapping error\n");;
memset(entry, 0, 12);
entry->LINIP = cb_desc->bLastIniPkt;
entry->FirstSeg = 1;
......
......@@ -2104,7 +2104,10 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev)
skb_tail_pointer_rsl(skb),
priv->rxbuffersize,
PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(priv->pdev, *mapping)) {
dev_kfree_skb_any(skb);
return -1;
}
entry->BufferAddress = cpu_to_le32(*mapping);
entry->Length = priv->rxbuffersize;
......@@ -2397,7 +2400,11 @@ static void rtl8192_rx_normal(struct net_device *dev)
skb_tail_pointer_rsl(skb),
priv->rxbuffersize,
PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(priv->pdev,
*((dma_addr_t *)skb->cb))) {
dev_kfree_skb_any(skb);
return;
}
}
done:
pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
......
......@@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {
{USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */
/* Belkin */
{USB_DEVICE(0x050D, 0x945A)},
/* ISY IWL - Belkin clone */
{USB_DEVICE(0x050D, 0x11F1)},
/* Corega */
{USB_DEVICE(0x07AA, 0x0047)},
/* D-Link */
......
......@@ -2,6 +2,7 @@ config SB105X
tristate "SystemBase PCI Multiport UART"
select SERIAL_CORE
depends on PCI
depends on X86
help
A driver for the SystemBase Multi-2/PCI serial card
......
......@@ -3054,6 +3054,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16);
}
break;
#ifdef CONFIG_PARPORT
case PCI_DEVICE_ID_MP2S1P :
sbdev->nr_ports = 2;
......@@ -3073,6 +3074,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
/* add PC compatible parallel port */
parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
break;
#endif
}
ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name);
......
......@@ -342,7 +342,7 @@ int synth_init(char *synth_name)
mutex_lock(&spk_mutex);
/* First, check if we already have it loaded. */
for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
if (strcmp(synths[i]->name, synth_name) == 0)
synth = synths[i];
......@@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth)
int i;
int status = 0;
mutex_lock(&spk_mutex);
for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
/* synth_remove() is responsible for rotating the array down */
if (in_synth == synths[i]) {
mutex_unlock(&spk_mutex);
......
......@@ -31,7 +31,7 @@
* driver should read or write to PRM/CM registers directly; they
* should rely on OMAP core code to do this.
*/
#include <mach-omap2/cm2xxx_3xxx.h>
#include <mach-omap2/cm3xxx.h>
#include <mach-omap2/prm-regbits-34xx.h>
#include <mach-omap2/cm-regbits-34xx.h>
#include <dspbridge/devdefs.h>
......
......@@ -121,9 +121,13 @@ void dsp_clk_exit(void)
for (i = 0; i < DM_TIMER_CLOCKS; i++)
omap_dm_timer_free(timer[i]);
clk_unprepare(iva2_clk);
clk_put(iva2_clk);
clk_unprepare(ssi.sst_fck);
clk_put(ssi.sst_fck);
clk_unprepare(ssi.ssr_fck);
clk_put(ssi.ssr_fck);
clk_unprepare(ssi.ick);
clk_put(ssi.ick);
}
......@@ -145,14 +149,21 @@ void dsp_clk_init(void)
iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck");
if (IS_ERR(iva2_clk))
dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk);
else
clk_prepare(iva2_clk);
ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck");
ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck");
ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick");
if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick))
if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) {
dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n",
ssi.sst_fck, ssi.ssr_fck, ssi.ick);
} else {
clk_prepare(ssi.sst_fck);
clk_prepare(ssi.ssr_fck);
clk_prepare(ssi.ick);
}
}
/**
......
......@@ -63,11 +63,15 @@ int dsp_wdt_init(void)
dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
if (!IS_ERR(dsp_wdt.fclk)) {
clk_prepare(dsp_wdt.fclk);
dsp_wdt.iclk = clk_get(NULL, "wdt3_ick");
if (IS_ERR(dsp_wdt.iclk)) {
clk_put(dsp_wdt.fclk);
dsp_wdt.fclk = NULL;
ret = -EFAULT;
} else {
clk_prepare(dsp_wdt.iclk);
}
} else
ret = -EFAULT;
......@@ -95,10 +99,14 @@ void dsp_wdt_exit(void)
free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
tasklet_kill(&dsp_wdt.wdt3_tasklet);
if (dsp_wdt.fclk)
if (dsp_wdt.fclk) {
clk_unprepare(dsp_wdt.fclk);
clk_put(dsp_wdt.fclk);
if (dsp_wdt.iclk)
}
if (dsp_wdt.iclk) {
clk_unprepare(dsp_wdt.iclk);
clk_put(dsp_wdt.iclk);
}
dsp_wdt.fclk = NULL;
dsp_wdt.iclk = NULL;
......
......@@ -162,11 +162,9 @@ static struct vme_driver pio2_driver = {
static int __init pio2_init(void)
{
int retval = 0;
if (bus_num == 0) {
pr_err("No cards, skipping registration\n");
goto err_nocard;
return -ENODEV;
}
if (bus_num > PIO2_CARDS_MAX) {
......@@ -176,15 +174,7 @@ static int __init pio2_init(void)
}
/* Register the PIO2 driver */
retval = vme_register_driver(&pio2_driver, bus_num);
if (retval != 0)
goto err_reg;
return retval;
err_reg:
err_nocard:
return retval;
return vme_register_driver(&pio2_driver, bus_num);
}
static int pio2_match(struct vme_dev *vdev)
......
......@@ -638,8 +638,8 @@ int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
}
int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type,
int mbm)
int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm)
{
struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
wlandevice_t *wlandev = priv->wlandev;
......@@ -665,7 +665,8 @@ int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type,
return err;
}
int prism2_get_tx_power(struct wiphy *wiphy, int *dbm)
int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
int *dbm)
{
struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
wlandevice_t *wlandev = priv->wlandev;
......
......@@ -265,7 +265,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
int offset)
{
int ret;
int ret = 0;
size_t clen;
unsigned long handle;
struct page *page;
......@@ -286,11 +286,9 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
goto out;
}
ret = zram_decompress_page(zram, uncmem, index);
if (ret) {
kfree(uncmem);
if (ret)
goto out;
}
}
/*
* System overwrites unused sectors. Free memory associated
......@@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
user_mem = kmap_atomic(page);
if (is_partial_io(bvec))
if (is_partial_io(bvec)) {
memcpy(uncmem + offset, user_mem + bvec->bv_offset,
bvec->bv_len);
else
kunmap_atomic(user_mem);
user_mem = NULL;
} else {
uncmem = user_mem;
}
if (page_zero_filled(uncmem)) {
if (!is_partial_io(bvec))
kunmap_atomic(user_mem);
if (is_partial_io(bvec))
kfree(uncmem);
zram_stat_inc(&zram->stats.pages_zero);
zram_set_flag(zram, index, ZRAM_ZERO);
ret = 0;
......@@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
zram->compress_workmem);
if (!is_partial_io(bvec)) {
kunmap_atomic(user_mem);
if (is_partial_io(bvec))
kfree(uncmem);
user_mem = NULL;
uncmem = NULL;
}
if (unlikely(ret != LZO_E_OK)) {
pr_err("Compression failed! err=%d\n", ret);
......@@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
if (unlikely(clen > max_zpage_size)) {
zram_stat_inc(&zram->stats.bad_compress);
src = uncmem;
clen = PAGE_SIZE;
src = NULL;
if (is_partial_io(bvec))
src = uncmem;
}
handle = zs_malloc(zram->mem_pool, clen);
......@@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
}
cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO);
if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
src = kmap_atomic(page);
memcpy(cmem, src, clen);
if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
kunmap_atomic(src);
zs_unmap_object(zram->mem_pool, handle);
......@@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
if (clen <= PAGE_SIZE / 2)
zram_stat_inc(&zram->stats.good_compress);
return 0;
out:
if (is_partial_io(bvec))
kfree(uncmem);
if (ret)
zram_stat64_inc(zram, &zram->stats.failed_writes);
return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment