Commit e8e35733 authored by Laurent Pinchart's avatar Laurent Pinchart

drm: xlnx: zynqmp_dpsub: Move encoder to DPSUB core

As part of the transitition of the DP encoder to a DRM bridge, turn the
DRM encoder into a dummy encoder and move it out of the DP code, to the
DPSUB core. DP encoder operations are handled by the DP bridge, which is
now attached to the encoder.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
parent 2374b6ea
...@@ -15,12 +15,10 @@ ...@@ -15,12 +15,10 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_device.h> #include <drm/drm_device.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_encoder.h>
#include <drm/drm_managed.h> #include <drm/drm_managed.h>
#include <drm/drm_modes.h> #include <drm/drm_modes.h>
#include <drm/drm_of.h> #include <drm/drm_of.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -277,7 +275,6 @@ struct zynqmp_dp_config { ...@@ -277,7 +275,6 @@ struct zynqmp_dp_config {
/** /**
* struct zynqmp_dp - Xilinx DisplayPort core * struct zynqmp_dp - Xilinx DisplayPort core
* @encoder: the drm encoder structure
* @connector: the drm connector structure * @connector: the drm connector structure
* @dev: device structure * @dev: device structure
* @dpsub: Display subsystem * @dpsub: Display subsystem
...@@ -299,7 +296,6 @@ struct zynqmp_dp_config { ...@@ -299,7 +296,6 @@ struct zynqmp_dp_config {
* @train_set: set of training data * @train_set: set of training data
*/ */
struct zynqmp_dp { struct zynqmp_dp {
struct drm_encoder encoder;
struct drm_connector connector; struct drm_connector connector;
struct device *dev; struct device *dev;
struct zynqmp_dpsub *dpsub; struct zynqmp_dpsub *dpsub;
...@@ -324,11 +320,6 @@ struct zynqmp_dp { ...@@ -324,11 +320,6 @@ struct zynqmp_dp {
u8 train_set[ZYNQMP_DP_MAX_LANES]; u8 train_set[ZYNQMP_DP_MAX_LANES];
}; };
static inline struct zynqmp_dp *encoder_to_dp(struct drm_encoder *encoder)
{
return container_of(encoder, struct zynqmp_dp, encoder);
}
static inline struct zynqmp_dp *connector_to_dp(struct drm_connector *connector) static inline struct zynqmp_dp *connector_to_dp(struct drm_connector *connector)
{ {
return container_of(connector, struct zynqmp_dp, connector); return container_of(connector, struct zynqmp_dp, connector);
...@@ -1566,7 +1557,7 @@ zynqmp_dp_connector_best_encoder(struct drm_connector *connector) ...@@ -1566,7 +1557,7 @@ zynqmp_dp_connector_best_encoder(struct drm_connector *connector)
{ {
struct zynqmp_dp *dp = connector_to_dp(connector); struct zynqmp_dp *dp = connector_to_dp(connector);
return &dp->encoder; return &dp->dpsub->encoder;
} }
static int zynqmp_dp_connector_mode_valid(struct drm_connector *connector, static int zynqmp_dp_connector_mode_valid(struct drm_connector *connector,
...@@ -1594,55 +1585,6 @@ zynqmp_dp_connector_helper_funcs = { ...@@ -1594,55 +1585,6 @@ zynqmp_dp_connector_helper_funcs = {
.mode_valid = zynqmp_dp_connector_mode_valid, .mode_valid = zynqmp_dp_connector_mode_valid,
}; };
/* -----------------------------------------------------------------------------
* DRM Encoder
*/
static void zynqmp_dp_encoder_atomic_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct zynqmp_dp *dp = encoder_to_dp(encoder);
struct drm_bridge_state bridge_state;
bridge_state.base.state = state;
zynqmp_dp_bridge_atomic_enable(&dp->bridge, &bridge_state);
}
static void zynqmp_dp_encoder_atomic_disable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct zynqmp_dp *dp = encoder_to_dp(encoder);
struct drm_bridge_state bridge_state;
bridge_state.base.state = state;
zynqmp_dp_bridge_atomic_disable(&dp->bridge, &bridge_state);
}
static void
zynqmp_dp_encoder_atomic_mode_set(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *connector_state)
{
}
static int
zynqmp_dp_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct zynqmp_dp *dp = encoder_to_dp(encoder);
return zynqmp_dp_bridge_atomic_check(&dp->bridge, NULL, crtc_state,
conn_state);
}
static const struct drm_encoder_helper_funcs zynqmp_dp_encoder_helper_funcs = {
.atomic_enable = zynqmp_dp_encoder_atomic_enable,
.atomic_disable = zynqmp_dp_encoder_atomic_disable,
.atomic_mode_set = zynqmp_dp_encoder_atomic_mode_set,
.atomic_check = zynqmp_dp_encoder_atomic_check,
};
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Interrupt Handling * Interrupt Handling
*/ */
...@@ -1731,32 +1673,17 @@ int zynqmp_dp_drm_init(struct zynqmp_dpsub *dpsub) ...@@ -1731,32 +1673,17 @@ int zynqmp_dp_drm_init(struct zynqmp_dpsub *dpsub)
{ {
struct zynqmp_dp *dp = dpsub->dp; struct zynqmp_dp *dp = dpsub->dp;
struct drm_bridge *bridge = &dp->bridge; struct drm_bridge *bridge = &dp->bridge;
struct drm_encoder *encoder = &dp->encoder;
int ret; int ret;
dp->config.misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK; dp->config.misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK;
zynqmp_dp_set_format(dp, NULL, ZYNQMP_DPSUB_FORMAT_RGB, 8); zynqmp_dp_set_format(dp, NULL, ZYNQMP_DPSUB_FORMAT_RGB, 8);
/* /* Initialize the bridge. */
* Initialize the bridge. Setting the device and encoder manually is a
* hack, to be removed once the bridge will get attached to the encoder
* using the bridge API.
*/
bridge->dev = dp->drm;
bridge->encoder = &dp->encoder;
bridge->funcs = &zynqmp_dp_bridge_funcs; bridge->funcs = &zynqmp_dp_bridge_funcs;
bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
| DRM_BRIDGE_OP_HPD; | DRM_BRIDGE_OP_HPD;
bridge->type = DRM_MODE_CONNECTOR_DisplayPort; bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
dpsub->bridge = bridge;
/* Create the DRM encoder and attach the bridge. */
encoder->possible_crtcs |= zynqmp_disp_get_crtc_mask(dpsub->disp);
drm_simple_encoder_init(dp->drm, encoder, DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &zynqmp_dp_encoder_helper_funcs);
ret = zynqmp_dp_bridge_attach(bridge, 0);
if (ret < 0)
return ret;
/* Initialize and register the AUX adapter. */ /* Initialize and register the AUX adapter. */
ret = zynqmp_dp_aux_init(dp); ret = zynqmp_dp_aux_init(dp);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_device.h> #include <drm/drm_device.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
#include <drm/drm_mode_config.h> #include <drm/drm_mode_config.h>
#include <drm/drm_module.h> #include <drm/drm_module.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h> #include <drm/drm_vblank.h>
#include "zynqmp_disp.h" #include "zynqmp_disp.h"
...@@ -94,6 +96,7 @@ static const struct drm_driver zynqmp_dpsub_drm_driver = { ...@@ -94,6 +96,7 @@ static const struct drm_driver zynqmp_dpsub_drm_driver = {
static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub) static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
{ {
struct drm_encoder *encoder = &dpsub->encoder;
struct drm_device *drm = &dpsub->drm; struct drm_device *drm = &dpsub->drm;
int ret; int ret;
...@@ -116,8 +119,7 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub) ...@@ -116,8 +119,7 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
/* /*
* Initialize the DISP and DP components. This will creates planes, * Initialize the DISP and DP components. This will creates planes,
* CRTC, encoder and connector. The DISP should be initialized first as * CRTC, and a bridge for the DP encoder.
* the DP encoder needs the CRTC.
*/ */
ret = zynqmp_disp_drm_init(dpsub); ret = zynqmp_disp_drm_init(dpsub);
if (ret) if (ret)
...@@ -127,6 +129,16 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub) ...@@ -127,6 +129,16 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
if (ret) if (ret)
goto err_poll_fini; goto err_poll_fini;
/* Create the encoder and attach the bridge. */
encoder->possible_crtcs |= zynqmp_disp_get_crtc_mask(dpsub->disp);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE);
ret = drm_bridge_attach(encoder, dpsub->bridge, NULL, 0);
if (ret) {
dev_err(dpsub->dev, "failed to attach bridge to encoder\n");
goto err_poll_fini;
}
/* Reset all components and register the DRM device. */ /* Reset all components and register the DRM device. */
drm_mode_config_reset(drm); drm_mode_config_reset(drm);
......
...@@ -12,8 +12,11 @@ ...@@ -12,8 +12,11 @@
#ifndef _ZYNQMP_DPSUB_H_ #ifndef _ZYNQMP_DPSUB_H_
#define _ZYNQMP_DPSUB_H_ #define _ZYNQMP_DPSUB_H_
#include <drm/drm_encoder.h>
struct clk; struct clk;
struct device; struct device;
struct drm_bridge;
struct drm_device; struct drm_device;
struct zynqmp_disp; struct zynqmp_disp;
struct zynqmp_dp; struct zynqmp_dp;
...@@ -30,6 +33,8 @@ enum zynqmp_dpsub_format { ...@@ -30,6 +33,8 @@ enum zynqmp_dpsub_format {
* @drm: The DRM/KMS device * @drm: The DRM/KMS device
* @dev: The physical device * @dev: The physical device
* @apb_clk: The APB clock * @apb_clk: The APB clock
* @encoder: The dummy DRM encoder
* @bridge: The DP encoder bridge
* @disp: The display controller * @disp: The display controller
* @dp: The DisplayPort controller * @dp: The DisplayPort controller
* @dma_align: DMA alignment constraint (must be a power of 2) * @dma_align: DMA alignment constraint (must be a power of 2)
...@@ -40,6 +45,9 @@ struct zynqmp_dpsub { ...@@ -40,6 +45,9 @@ struct zynqmp_dpsub {
struct clk *apb_clk; struct clk *apb_clk;
struct drm_encoder encoder;
struct drm_bridge *bridge;
struct zynqmp_disp *disp; struct zynqmp_disp *disp;
struct zynqmp_dp *dp; struct zynqmp_dp *dp;
......
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