Skip to content

Commit

Permalink
Merge branch 'drm/next/atomic' of git://linuxtv.org/pinchartl/fbdev i…
Browse files Browse the repository at this point in the history
…nto drm-next

rcar-du atomic modesetting support
* 'drm/next/atomic' of git://linuxtv.org/pinchartl/fbdev: (32 commits)
  drm: rcar-du: Fix race condition in hardware plane allocator
  drm: rcar-du: Move group locking inside rcar_du_crtc_update_planes()
  drm: rcar-du: Move plane commit code from CRTC start to CRTC resume
  drm: rcar-du: Move plane format to plane state
  drm: rcar-du: Remove unneeded rcar_du_crtc plane field
  drm: rcar-du: Replace plane crtc and enabled fields by plane state
  drm: rcar-du: Rework plane setup code
  drm: rcar-du: Switch plane set_property to atomic helpers
  drm: rcar-du: Switch page flip to atomic helpers
  drm: rcar-du: Implement asynchronous commit support
  drm: rcar-du: Replace encoder mode_fixup with atomic_check
  drm: rcar-du: Switch connector DPMS to atomic helpers
  drm: rcar-du: Switch mode config to atomic helpers
  drm: rcar-du: Switch plane update to atomic helpers
  drm: rcar-du: Rework CRTC enable/disable for atomic updates
  drm: rcar-du: Rework HDMI encoder enable/disable for atomic updates
  drm: rcar-du: Rework encoder enable/disable for atomic updates
  drm: rcar-du: Replace LVDS encoder DPMS by enable/disable
  drm: rcar-du: Remove private copy of plane size and position
  drm: rcar-du: Wire up atomic state object scaffolding
  ...
  • Loading branch information
Dave Airlie committed Mar 4, 2015
2 parents 79d6d94 + 5ee5a81 commit 7e47748
Show file tree
Hide file tree
Showing 15 changed files with 822 additions and 634 deletions.
400 changes: 185 additions & 215 deletions drivers/gpu/drm/rcar-du/rcar_du_crtc.c

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions drivers/gpu/drm/rcar-du/rcar_du_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
#define __RCAR_DU_CRTC_H__

#include <linux/mutex.h>
#include <linux/wait.h>

#include <drm/drmP.h>
#include <drm/drm_crtc.h>

struct rcar_du_group;
struct rcar_du_plane;

struct rcar_du_crtc {
struct drm_crtc crtc;
Expand All @@ -32,11 +32,12 @@ struct rcar_du_crtc {
bool started;

struct drm_pending_vblank_event *event;
wait_queue_head_t flip_wait;

unsigned int outputs;
int dpms;
bool enabled;

struct rcar_du_group *group;
struct rcar_du_plane *plane;
};

#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
Expand All @@ -59,6 +60,5 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);

void rcar_du_crtc_route_output(struct drm_crtc *crtc,
enum rcar_du_output output);
void rcar_du_crtc_update_planes(struct drm_crtc *crtc);

#endif /* __RCAR_DU_CRTC_H__ */
17 changes: 11 additions & 6 deletions drivers/gpu/drm/rcar-du/rcar_du_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/wait.h>

#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
Expand Down Expand Up @@ -163,6 +164,8 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
return -ENOMEM;
}

init_waitqueue_head(&rcdu->commit.wait);

rcdu->dev = &pdev->dev;
rcdu->info = np ? of_match_device(rcar_du_of_table, rcdu->dev)->data
: (void *)platform_get_device_id(pdev)->driver_data;
Expand All @@ -175,17 +178,19 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
if (IS_ERR(rcdu->mmio))
return PTR_ERR(rcdu->mmio);

/* DRM/KMS objects */
ret = rcar_du_modeset_init(rcdu);
/* Initialize vertical blanking interrupts handling. Start with vblank
* disabled for all CRTCs.
*/
ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize DRM/KMS\n");
dev_err(&pdev->dev, "failed to initialize vblank\n");
goto done;
}

/* vblank handling */
ret = drm_vblank_init(dev, (1 << rcdu->num_crtcs) - 1);
/* DRM/KMS objects */
ret = rcar_du_modeset_init(rcdu);
if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize vblank\n");
dev_err(&pdev->dev, "failed to initialize DRM/KMS\n");
goto done;
}

Expand Down
16 changes: 13 additions & 3 deletions drivers/gpu/drm/rcar-du/rcar_du_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define __RCAR_DU_DRV_H__

#include <linux/kernel.h>
#include <linux/wait.h>

#include "rcar_du_crtc.h"
#include "rcar_du_group.h"
Expand Down Expand Up @@ -64,6 +65,10 @@ struct rcar_du_device_info {
unsigned int num_lvds;
};

#define RCAR_DU_MAX_CRTCS 3
#define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
#define RCAR_DU_MAX_LVDS 2

struct rcar_du_device {
struct device *dev;
const struct rcar_du_device_info *info;
Expand All @@ -73,13 +78,18 @@ struct rcar_du_device {
struct drm_device *ddev;
struct drm_fbdev_cma *fbdev;

struct rcar_du_crtc crtcs[3];
struct rcar_du_crtc crtcs[RCAR_DU_MAX_CRTCS];
unsigned int num_crtcs;

struct rcar_du_group groups[2];
struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];

unsigned int dpad0_source;
struct rcar_du_lvdsenc *lvds[2];
struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];

struct {
wait_queue_head_t wait;
u32 pending;
} commit;
};

static inline bool rcar_du_has(struct rcar_du_device *rcdu,
Expand Down
71 changes: 23 additions & 48 deletions drivers/gpu/drm/rcar-du/rcar_du_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,46 +42,40 @@ rcar_du_connector_best_encoder(struct drm_connector *connector)
* Encoder
*/

static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode)
static void rcar_du_encoder_disable(struct drm_encoder *encoder)
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);

if (mode != DRM_MODE_DPMS_ON)
mode = DRM_MODE_DPMS_OFF;
if (renc->lvds)
rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false);
}

static void rcar_du_encoder_enable(struct drm_encoder *encoder)
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);

if (renc->lvds)
rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc, mode);
rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);
}

static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
const struct drm_display_mode *mode = &crtc_state->mode;
const struct drm_display_mode *panel_mode;
struct drm_connector *connector = conn_state->connector;
struct drm_device *dev = encoder->dev;
struct drm_connector *connector;
bool found = false;

/* DAC encoders have currently no restriction on the mode. */
if (encoder->encoder_type == DRM_MODE_ENCODER_DAC)
return true;

list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->encoder == encoder) {
found = true;
break;
}
}

if (!found) {
dev_dbg(dev->dev, "mode_fixup: no connector found\n");
return false;
}
return 0;

if (list_empty(&connector->modes)) {
dev_dbg(dev->dev, "mode_fixup: empty modes list\n");
return false;
dev_dbg(dev->dev, "encoder: empty modes list\n");
return -EINVAL;
}

panel_mode = list_first_entry(&connector->modes,
Expand All @@ -90,7 +84,7 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
/* We're not allowed to modify the resolution. */
if (mode->hdisplay != panel_mode->hdisplay ||
mode->vdisplay != panel_mode->vdisplay)
return false;
return -EINVAL;

/* The flat panel mode is fixed, just copy it to the adjusted mode. */
drm_mode_copy(adjusted_mode, panel_mode);
Expand All @@ -102,25 +96,7 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
adjusted_mode->clock = clamp(adjusted_mode->clock,
30000, 150000);

return true;
}

static void rcar_du_encoder_mode_prepare(struct drm_encoder *encoder)
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);

if (renc->lvds)
rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc,
DRM_MODE_DPMS_OFF);
}

static void rcar_du_encoder_mode_commit(struct drm_encoder *encoder)
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);

if (renc->lvds)
rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc,
DRM_MODE_DPMS_ON);
return 0;
}

static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
Expand All @@ -133,11 +109,10 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
}

static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
.dpms = rcar_du_encoder_dpms,
.mode_fixup = rcar_du_encoder_mode_fixup,
.prepare = rcar_du_encoder_mode_prepare,
.commit = rcar_du_encoder_mode_commit,
.mode_set = rcar_du_encoder_mode_set,
.disable = rcar_du_encoder_disable,
.enable = rcar_du_encoder_enable,
.atomic_check = rcar_du_encoder_atomic_check,
};

static const struct drm_encoder_funcs encoder_funcs = {
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#ifndef __RCAR_DU_GROUP_H__
#define __RCAR_DU_GROUP_H__

#include <linux/mutex.h>

#include "rcar_du_plane.h"

struct rcar_du_device;
Expand All @@ -25,6 +27,7 @@ struct rcar_du_device;
* @index: group index
* @use_count: number of users of the group (rcar_du_group_(get|put))
* @used_crtcs: number of CRTCs currently in use
* @lock: protects the DPTSR register
* @planes: planes handled by the group
*/
struct rcar_du_group {
Expand All @@ -35,6 +38,8 @@ struct rcar_du_group {
unsigned int use_count;
unsigned int used_crtcs;

struct mutex lock;

struct rcar_du_planes planes;
};

Expand Down
9 changes: 6 additions & 3 deletions drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_encoder_slave.h>
Expand Down Expand Up @@ -74,10 +75,13 @@ rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
}

static const struct drm_connector_funcs connector_funcs = {
.dpms = drm_helper_connector_dpms,
.dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_hdmi_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};

int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
Expand Down Expand Up @@ -108,15 +112,14 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
if (ret < 0)
return ret;

drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,
rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);

ret = drm_mode_connector_attach_encoder(connector, encoder);
if (ret < 0)
return ret;

connector->encoder = encoder;
rcon->encoder = renc;

return 0;
Expand Down
Loading

0 comments on commit 7e47748

Please sign in to comment.