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
  ...
This commit is contained in:
Linus Torvalds
2013-01-14 09:08:38 -08:00
51 changed files with 1405 additions and 998 deletions
+1
View File
@@ -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
+3
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}
+8 -8
View File
@@ -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 -1
View File
@@ -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.
+3 -11
View File
@@ -1,5 +1,5 @@
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
+1 -1
View File
@@ -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)
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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.
-1
View File
@@ -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;
}
+4 -1
View File
@@ -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 @@ failed_add_clients:
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:
+4 -2
View File
@@ -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);
+1
View File
@@ -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 \
-3
View File
@@ -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
+10 -101
View File
@@ -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,
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+117 -23
View File
@@ -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?
*/
+66 -66
View File
@@ -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:
+1 -1
View File
@@ -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,

Some files were not shown because too many files have changed in this diff Show More