Commit 7e477484 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm/next/atomic' of git://linuxtv.org/pinchartl/fbdev into 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
  ...
parents 79d6d942 5ee5a81d
This diff is collapsed.
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
#define __RCAR_DU_CRTC_H__ #define __RCAR_DU_CRTC_H__
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/wait.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
struct rcar_du_group; struct rcar_du_group;
struct rcar_du_plane;
struct rcar_du_crtc { struct rcar_du_crtc {
struct drm_crtc crtc; struct drm_crtc crtc;
...@@ -32,11 +32,12 @@ struct rcar_du_crtc { ...@@ -32,11 +32,12 @@ struct rcar_du_crtc {
bool started; bool started;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
wait_queue_head_t flip_wait;
unsigned int outputs; unsigned int outputs;
int dpms; bool enabled;
struct rcar_du_group *group; struct rcar_du_group *group;
struct rcar_du_plane *plane;
}; };
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc) #define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
...@@ -59,6 +60,5 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc); ...@@ -59,6 +60,5 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
void rcar_du_crtc_route_output(struct drm_crtc *crtc, void rcar_du_crtc_route_output(struct drm_crtc *crtc,
enum rcar_du_output output); enum rcar_du_output output);
void rcar_du_crtc_update_planes(struct drm_crtc *crtc);
#endif /* __RCAR_DU_CRTC_H__ */ #endif /* __RCAR_DU_CRTC_H__ */
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/wait.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
...@@ -163,6 +164,8 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags) ...@@ -163,6 +164,8 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
return -ENOMEM; return -ENOMEM;
} }
init_waitqueue_head(&rcdu->commit.wait);
rcdu->dev = &pdev->dev; rcdu->dev = &pdev->dev;
rcdu->info = np ? of_match_device(rcar_du_of_table, rcdu->dev)->data rcdu->info = np ? of_match_device(rcar_du_of_table, rcdu->dev)->data
: (void *)platform_get_device_id(pdev)->driver_data; : (void *)platform_get_device_id(pdev)->driver_data;
...@@ -175,17 +178,19 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags) ...@@ -175,17 +178,19 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
if (IS_ERR(rcdu->mmio)) if (IS_ERR(rcdu->mmio))
return PTR_ERR(rcdu->mmio); return PTR_ERR(rcdu->mmio);
/* DRM/KMS objects */ /* Initialize vertical blanking interrupts handling. Start with vblank
ret = rcar_du_modeset_init(rcdu); * disabled for all CRTCs.
*/
ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize DRM/KMS\n"); dev_err(&pdev->dev, "failed to initialize vblank\n");
goto done; goto done;
} }
/* vblank handling */ /* DRM/KMS objects */
ret = drm_vblank_init(dev, (1 << rcdu->num_crtcs) - 1); ret = rcar_du_modeset_init(rcdu);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize vblank\n"); dev_err(&pdev->dev, "failed to initialize DRM/KMS\n");
goto done; goto done;
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define __RCAR_DU_DRV_H__ #define __RCAR_DU_DRV_H__
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/wait.h>
#include "rcar_du_crtc.h" #include "rcar_du_crtc.h"
#include "rcar_du_group.h" #include "rcar_du_group.h"
...@@ -64,6 +65,10 @@ struct rcar_du_device_info { ...@@ -64,6 +65,10 @@ struct rcar_du_device_info {
unsigned int num_lvds; 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 rcar_du_device {
struct device *dev; struct device *dev;
const struct rcar_du_device_info *info; const struct rcar_du_device_info *info;
...@@ -73,13 +78,18 @@ struct rcar_du_device { ...@@ -73,13 +78,18 @@ struct rcar_du_device {
struct drm_device *ddev; struct drm_device *ddev;
struct drm_fbdev_cma *fbdev; struct drm_fbdev_cma *fbdev;
struct rcar_du_crtc crtcs[3]; struct rcar_du_crtc crtcs[RCAR_DU_MAX_CRTCS];
unsigned int num_crtcs; unsigned int num_crtcs;
struct rcar_du_group groups[2]; struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
unsigned int dpad0_source; 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, static inline bool rcar_du_has(struct rcar_du_device *rcdu,
......
...@@ -42,46 +42,40 @@ rcar_du_connector_best_encoder(struct drm_connector *connector) ...@@ -42,46 +42,40 @@ rcar_du_connector_best_encoder(struct drm_connector *connector)
* Encoder * 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); struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
if (mode != DRM_MODE_DPMS_ON) if (renc->lvds)
mode = DRM_MODE_DPMS_OFF; 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) 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, static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
const struct drm_display_mode *mode, struct drm_crtc_state *crtc_state,
struct drm_display_mode *adjusted_mode) struct drm_connector_state *conn_state)
{ {
struct rcar_du_encoder *renc = to_rcar_encoder(encoder); 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; const struct drm_display_mode *panel_mode;
struct drm_connector *connector = conn_state->connector;
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_connector *connector;
bool found = false;
/* DAC encoders have currently no restriction on the mode. */ /* DAC encoders have currently no restriction on the mode. */
if (encoder->encoder_type == DRM_MODE_ENCODER_DAC) if (encoder->encoder_type == DRM_MODE_ENCODER_DAC)
return true; return 0;
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;
}
if (list_empty(&connector->modes)) { if (list_empty(&connector->modes)) {
dev_dbg(dev->dev, "mode_fixup: empty modes list\n"); dev_dbg(dev->dev, "encoder: empty modes list\n");
return false; return -EINVAL;
} }
panel_mode = list_first_entry(&connector->modes, panel_mode = list_first_entry(&connector->modes,
...@@ -90,7 +84,7 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder, ...@@ -90,7 +84,7 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
/* We're not allowed to modify the resolution. */ /* We're not allowed to modify the resolution. */
if (mode->hdisplay != panel_mode->hdisplay || if (mode->hdisplay != panel_mode->hdisplay ||
mode->vdisplay != panel_mode->vdisplay) mode->vdisplay != panel_mode->vdisplay)
return false; return -EINVAL;
/* The flat panel mode is fixed, just copy it to the adjusted mode. */ /* The flat panel mode is fixed, just copy it to the adjusted mode. */
drm_mode_copy(adjusted_mode, panel_mode); drm_mode_copy(adjusted_mode, panel_mode);
...@@ -102,25 +96,7 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder, ...@@ -102,25 +96,7 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
adjusted_mode->clock = clamp(adjusted_mode->clock, adjusted_mode->clock = clamp(adjusted_mode->clock,
30000, 150000); 30000, 150000);
return true; return 0;
}
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);
} }
static void rcar_du_encoder_mode_set(struct drm_encoder *encoder, static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
...@@ -133,11 +109,10 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder, ...@@ -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 = { 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, .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 = { static const struct drm_encoder_funcs encoder_funcs = {
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#ifndef __RCAR_DU_GROUP_H__ #ifndef __RCAR_DU_GROUP_H__
#define __RCAR_DU_GROUP_H__ #define __RCAR_DU_GROUP_H__
#include <linux/mutex.h>
#include "rcar_du_plane.h" #include "rcar_du_plane.h"
struct rcar_du_device; struct rcar_du_device;
...@@ -25,6 +27,7 @@ struct rcar_du_device; ...@@ -25,6 +27,7 @@ struct rcar_du_device;
* @index: group index * @index: group index
* @use_count: number of users of the group (rcar_du_group_(get|put)) * @use_count: number of users of the group (rcar_du_group_(get|put))
* @used_crtcs: number of CRTCs currently in use * @used_crtcs: number of CRTCs currently in use
* @lock: protects the DPTSR register
* @planes: planes handled by the group * @planes: planes handled by the group
*/ */
struct rcar_du_group { struct rcar_du_group {
...@@ -35,6 +38,8 @@ struct rcar_du_group { ...@@ -35,6 +38,8 @@ struct rcar_du_group {
unsigned int use_count; unsigned int use_count;
unsigned int used_crtcs; unsigned int used_crtcs;
struct mutex lock;
struct rcar_du_planes planes; struct rcar_du_planes planes;
}; };
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
*/ */
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_encoder_slave.h> #include <drm/drm_encoder_slave.h>
...@@ -74,10 +75,13 @@ rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force) ...@@ -74,10 +75,13 @@ rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
} }
static const struct drm_connector_funcs connector_funcs = { 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, .detect = rcar_du_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_hdmi_connector_destroy, .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, int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
...@@ -108,7 +112,7 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu, ...@@ -108,7 +112,7 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
if (ret < 0) if (ret < 0)
return ret; return ret;
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base, drm_object_property_set_value(&connector->base,
rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF); rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
...@@ -116,7 +120,6 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu, ...@@ -116,7 +120,6 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
if (ret < 0) if (ret < 0)
return ret; return ret;
connector->encoder = encoder;
rcon->encoder = renc; rcon->encoder = renc;
return 0; return 0;
......
...@@ -26,41 +26,50 @@ ...@@ -26,41 +26,50 @@
struct rcar_du_hdmienc { struct rcar_du_hdmienc {
struct rcar_du_encoder *renc; struct rcar_du_encoder *renc;
struct device *dev; struct device *dev;
int dpms; bool enabled;
}; };
#define to_rcar_hdmienc(e) (to_rcar_encoder(e)->hdmi) #define to_rcar_hdmienc(e) (to_rcar_encoder(e)->hdmi)
#define to_slave_funcs(e) (to_rcar_encoder(e)->slave.slave_funcs) #define to_slave_funcs(e) (to_rcar_encoder(e)->slave.slave_funcs)
static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode) static void rcar_du_hdmienc_disable(struct drm_encoder *encoder)
{ {
struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
if (mode != DRM_MODE_DPMS_ON) if (sfuncs->dpms)
mode = DRM_MODE_DPMS_OFF; sfuncs->dpms(encoder, DRM_MODE_DPMS_OFF);
if (hdmienc->dpms == mode) if (hdmienc->renc->lvds)
return; rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
false);
if (mode == DRM_MODE_DPMS_ON && hdmienc->renc->lvds) hdmienc->enabled = false;
rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode); }
if (sfuncs->dpms) static void rcar_du_hdmienc_enable(struct drm_encoder *encoder)
sfuncs->dpms(encoder, mode); {
struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
if (hdmienc->renc->lvds)
rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
true);
if (mode != DRM_MODE_DPMS_ON && hdmienc->renc->lvds) if (sfuncs->dpms)
rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode); sfuncs->dpms(encoder, DRM_MODE_DPMS_ON);
hdmienc->dpms = mode; hdmienc->enabled = true;
} }
static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder, static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
const struct drm_display_mode *mode, struct drm_crtc_state *crtc_state,
struct drm_display_mode *adjusted_mode) struct drm_connector_state *conn_state)
{ {
struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
const struct drm_display_mode *mode = &crtc_state->mode;
/* The internal LVDS encoder has a clock frequency operating range of /* The internal LVDS encoder has a clock frequency operating range of
* 30MHz to 150MHz. Clamp the clock accordingly. * 30MHz to 150MHz. Clamp the clock accordingly.
...@@ -70,19 +79,9 @@ static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder, ...@@ -70,19 +79,9 @@ static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder,
30000, 150000); 30000, 150000);
if (sfuncs->mode_fixup == NULL) if (sfuncs->mode_fixup == NULL)
return true; return 0;
return sfuncs->mode_fixup(encoder, mode, adjusted_mode);
}
static void rcar_du_hdmienc_mode_prepare(struct drm_encoder *encoder)
{
rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_OFF);
}
static void rcar_du_hdmienc_mode_commit(struct drm_encoder *encoder) return sfuncs->mode_fixup(encoder, mode, adjusted_mode) ? 0 : -EINVAL;
{
rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_ON);
} }
static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder, static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
...@@ -99,18 +98,18 @@ static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder, ...@@ -99,18 +98,18 @@ static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
} }
static const struct drm_encoder_helper_funcs encoder_helper_funcs = { static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
.dpms = rcar_du_hdmienc_dpms,
.mode_fixup = rcar_du_hdmienc_mode_fixup,
.prepare = rcar_du_hdmienc_mode_prepare,
.commit = rcar_du_hdmienc_mode_commit,
.mode_set = rcar_du_hdmienc_mode_set, .mode_set = rcar_du_hdmienc_mode_set,
.disable = rcar_du_hdmienc_disable,
.enable = rcar_du_hdmienc_enable,
.atomic_check = rcar_du_hdmienc_atomic_check,
}; };
static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder) static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder)
{ {
struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_OFF); if (hdmienc->enabled)
rcar_du_hdmienc_disable(encoder);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
put_device(hdmienc->dev); put_device(hdmienc->dev);
......
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
*/ */
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
...@@ -74,10 +75,13 @@ rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force) ...@@ -74,10 +75,13 @@ rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
} }
static const struct drm_connector_funcs connector_funcs = { 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_lvds_connector_detect, .detect = rcar_du_lvds_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_lvds_connector_destroy, .destroy = rcar_du_lvds_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
}; };
int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu, int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
...@@ -117,7 +121,7 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu, ...@@ -117,7 +121,7 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
if (ret < 0) if (ret < 0)
return ret; return ret;
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base, drm_object_property_set_value(&connector->base,
rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF); rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
...@@ -125,7 +129,6 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu, ...@@ -125,7 +129,6 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
if (ret < 0) if (ret < 0)
return ret; return ret;
connector->encoder = encoder;
lvdscon->connector.encoder = renc; lvdscon->connector.encoder = renc;
return 0; return 0;
......
...@@ -28,7 +28,7 @@ struct rcar_du_lvdsenc { ...@@ -28,7 +28,7 @@ struct rcar_du_lvdsenc {
unsigned int index; unsigned int index;
void __iomem *mmio; void __iomem *mmio;
struct clk *clock; struct clk *clock;
int dpms; bool enabled;
enum rcar_lvds_input input; enum rcar_lvds_input input;
}; };
...@@ -48,7 +48,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, ...@@ -48,7 +48,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
u32 pllcr; u32 pllcr;
int ret; int ret;
if (lvds->dpms == DRM_MODE_DPMS_ON) if (lvds->enabled)
return 0; return 0;
ret = clk_prepare_enable(lvds->clock); ret = clk_prepare_enable(lvds->clock);
...@@ -110,13 +110,13 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, ...@@ -110,13 +110,13 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
lvdcr0 |= LVDCR0_LVRES; lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0); rcar_lvds_write(lvds, LVDCR0, lvdcr0);
lvds->dpms = DRM_MODE_DPMS_ON; lvds->enabled = true;
return 0; return 0;
} }
static void rcar_du_lvdsenc_stop(struct rcar_du_lvdsenc *lvds) static void rcar_du_lvdsenc_stop(struct rcar_du_lvdsenc *lvds)
{ {
if (lvds->dpms == DRM_MODE_DPMS_OFF) if (!lvds->enabled)
return; return;
rcar_lvds_write(lvds, LVDCR0, 0); rcar_lvds_write(lvds, LVDCR0, 0);
...@@ -124,13 +124,13 @@ static void rcar_du_lvdsenc_stop(struct rcar_du_lvdsenc *lvds) ...@@ -124,13 +124,13 @@ static void rcar_du_lvdsenc_stop(struct rcar_du_lvdsenc *lvds)
clk_disable_unprepare(lvds->clock); clk_disable_unprepare(lvds->clock);
lvds->dpms = DRM_MODE_DPMS_OFF; lvds->enabled = false;
} }
int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds, int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
struct drm_crtc *crtc, int mode) bool enable)
{ {
if (mode == DRM_MODE_DPMS_OFF) { if (!enable) {
rcar_du_lvdsenc_stop(lvds); rcar_du_lvdsenc_stop(lvds);
return 0; return 0;
} else if (crtc) { } else if (crtc) {
...@@ -179,7 +179,7 @@ int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu) ...@@ -179,7 +179,7 @@ int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
lvds->dev = rcdu; lvds->dev = rcdu;
lvds->index = i; lvds->index = i;
lvds->input = i ? RCAR_LVDS_INPUT_DU1 : RCAR_LVDS_INPUT_DU0; lvds->input = i ? RCAR_LVDS_INPUT_DU1 : RCAR_LVDS_INPUT_DU0;
lvds->dpms = DRM_MODE_DPMS_OFF; lvds->enabled = false;
ret = rcar_du_lvdsenc_get_resources(lvds, pdev); ret = rcar_du_lvdsenc_get_resources(lvds, pdev);
if (ret < 0) if (ret < 0)
......
...@@ -28,15 +28,15 @@ enum rcar_lvds_input { ...@@ -28,15 +28,15 @@ enum rcar_lvds_input {
#if IS_ENABLED(CONFIG_DRM_RCAR_LVDS) #if IS_ENABLED(CONFIG_DRM_RCAR_LVDS)
int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu); int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu);
int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds, int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
struct drm_crtc *crtc, int mode); struct drm_crtc *crtc, bool enable);
#else #else
static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu) static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
{ {
return 0; return 0;
} }
static inline int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds, static inline int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
struct drm_crtc *crtc, int mode) struct drm_crtc *crtc, bool enable)
{ {
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -14,68 +14,57 @@ ...@@ -14,68 +14,57 @@
#ifndef __RCAR_DU_PLANE_H__ #ifndef __RCAR_DU_PLANE_H__
#define __RCAR_DU_PLANE_H__ #define __RCAR_DU_PLANE_H__
#include <linux/mutex.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
struct rcar_du_format_info; struct rcar_du_format_info;
struct rcar_du_group; struct rcar_du_group;
/* The RCAR DU has 8 hardware planes, shared between KMS planes and CRTCs. As /* The RCAR DU has 8 hardware planes, shared between primary and overlay planes.
* using KMS planes requires at least one of the CRTCs being enabled, no more * As using overlay planes requires at least one of the CRTCs being enabled, no
* than 7 KMS planes can be available. We thus create 7 KMS planes and * more than 7 overlay planes can be available. We thus create 1 primary plane
* 9 software planes (one for each KMS planes and one for each CRTC). * per CRTC and 7 overlay planes, for a total of up to 9 KMS planes.
*/ */
#define RCAR_DU_NUM_KMS_PLANES 9
#define RCAR_DU_NUM_KMS_PLANES 7
#define RCAR_DU_NUM_HW_PLANES 8 #define RCAR_DU_NUM_HW_PLANES 8
#define RCAR_DU_NUM_SW_PLANES 9
struct rcar_du_plane { struct rcar_du_plane {
struct drm_plane plane;
struct rcar_du_group *group; struct rcar_du_group *group;
struct drm_crtc *crtc;
bool enabled;
int hwindex; /* 0-based, -1 means unused */
unsigned int alpha;
unsigned int colorkey;
unsigned int zpos;
const struct rcar_du_format_info *format;
unsigned long dma[2];
unsigned int pitch;
unsigned int width;
unsigned int height;
unsigned int src_x;
unsigned int src_y;
unsigned int dst_x;
unsigned int dst_y;
}; };
static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane)
{
return container_of(plane, struct rcar_du_plane, plane);
}
struct rcar_du_planes { struct rcar_du_planes {
struct rcar_du_plane planes[RCAR_DU_NUM_SW_PLANES]; struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
unsigned int free;
struct mutex lock;
struct drm_property *alpha; struct drm_property *alpha;
struct drm_property *colorkey; struct drm_property *colorkey;
struct drm_property *zpos; struct drm_property *zpos;
}; };
struct rcar_du_plane_state {
struct drm_plane_state state;
const struct rcar_du_format_info *format;
int hwindex; /* 0-based, -1 means unused */
unsigned int alpha;
unsigned int colorkey;
unsigned int zpos;
};
static inline struct rcar_du_plane_state *
to_rcar_du_plane_state(struct drm_plane_state *state)
{
return container_of(state, struct rcar_du_plane_state, state);
}
int rcar_du_planes_init(struct rcar_du_group *rgrp); int rcar_du_planes_init(struct rcar_du_group *rgrp);
int rcar_du_planes_register(struct rcar_du_group *rgrp);
void rcar_du_plane_setup(struct rcar_du_plane *plane); void rcar_du_plane_setup(struct rcar_du_plane *plane);
void rcar_du_plane_update_base(struct rcar_du_plane *plane);
void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
struct drm_framebuffer *fb);
int rcar_du_plane_reserve(struct rcar_du_plane *plane,
const struct rcar_du_format_info *format);
void rcar_du_plane_release(struct rcar_du_plane *plane);
#endif /* __RCAR_DU_PLANE_H__ */ #endif /* __RCAR_DU_PLANE_H__ */
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
*/ */
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
...@@ -43,10 +44,13 @@ rcar_du_vga_connector_detect(struct drm_connector *connector, bool force) ...@@ -43,10 +44,13 @@ rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
} }
static const struct drm_connector_funcs connector_funcs = { 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_vga_connector_detect, .detect = rcar_du_vga_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_vga_connector_destroy, .destroy = rcar_du_vga_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
}; };
int rcar_du_vga_connector_init(struct rcar_du_device *rcdu, int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
...@@ -76,7 +80,7 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu, ...@@ -76,7 +80,7 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
if (ret < 0) if (ret < 0)
return ret; return ret;
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base, drm_object_property_set_value(&connector->base,
rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF); rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
...@@ -84,7 +88,6 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu, ...@@ -84,7 +88,6 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
if (ret < 0) if (ret < 0)
return ret; return ret;
connector->encoder = encoder;
rcon->encoder = renc; rcon->encoder = renc;
return 0; return 0;
......
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