#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
#include "rcar_du_drv.h"
#include "rcar_du_encoder.h"
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+ if (renc->connector && renc->connector->panel) {
+ drm_panel_disable(renc->connector->panel);
+ drm_panel_unprepare(renc->connector->panel);
+ }
+
if (renc->lvds)
rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false);
}
if (renc->lvds)
rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);
+
+ if (renc->connector && renc->connector->panel) {
+ drm_panel_prepare(renc->connector->panel);
+ drm_panel_enable(renc->connector->panel);
+ }
}
static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
rcar_du_crtc_route_output(crtc_state->crtc, renc->output);
+
+ if (!renc->lvds) {
+ /*
+ * The DU driver creates connectors only for the outputs of the
+ * internal LVDS encoders.
+ */
+ renc->connector = NULL;
+ return;
+ }
+
+ renc->connector = to_rcar_connector(conn_state->connector);
}
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
#include <video/display_timing.h>
#include <video/of_display_timing.h>
#include "rcar_du_kms.h"
#include "rcar_du_lvdscon.h"
-struct rcar_du_lvds_connector {
- struct rcar_du_connector connector;
-
- struct {
- unsigned int width_mm; /* Panel width in mm */
- unsigned int height_mm; /* Panel height in mm */
- struct videomode mode;
- } panel;
-};
-
-#define to_rcar_lvds_connector(c) \
- container_of(c, struct rcar_du_lvds_connector, connector.connector)
-
static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector)
{
- struct rcar_du_lvds_connector *lvdscon =
- to_rcar_lvds_connector(connector);
- struct drm_display_mode *mode;
-
- mode = drm_mode_create(connector->dev);
- if (mode == NULL)
- return 0;
+ struct rcar_du_connector *rcon = to_rcar_connector(connector);
- mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
-
- drm_display_mode_from_videomode(&lvdscon->panel.mode, mode);
-
- drm_mode_probed_add(connector, mode);
-
- return 1;
+ return drm_panel_get_modes(rcon->panel);
}
static const struct drm_connector_helper_funcs connector_helper_funcs = {
.get_modes = rcar_du_lvds_connector_get_modes,
};
+static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
+{
+ struct rcar_du_connector *rcon = to_rcar_connector(connector);
+
+ drm_panel_detach(rcon->panel);
+ drm_connector_cleanup(connector);
+}
+
static const struct drm_connector_funcs connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
+ .destroy = rcar_du_lvds_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
const struct device_node *np)
{
struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
- struct rcar_du_lvds_connector *lvdscon;
+ struct rcar_du_connector *rcon;
struct drm_connector *connector;
- struct display_timing timing;
int ret;
- lvdscon = devm_kzalloc(rcdu->dev, sizeof(*lvdscon), GFP_KERNEL);
- if (lvdscon == NULL)
+ rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
+ if (rcon == NULL)
return -ENOMEM;
- ret = of_get_display_timing(np, "panel-timing", &timing);
- if (ret < 0)
- return ret;
-
- videomode_from_timing(&timing, &lvdscon->panel.mode);
+ connector = &rcon->connector;
- of_property_read_u32(np, "width-mm", &lvdscon->panel.width_mm);
- of_property_read_u32(np, "height-mm", &lvdscon->panel.height_mm);
-
- connector = &lvdscon->connector.connector;
- connector->display_info.width_mm = lvdscon->panel.width_mm;
- connector->display_info.height_mm = lvdscon->panel.height_mm;
+ rcon->panel = of_drm_find_panel(np);
+ if (!rcon->panel)
+ return -EPROBE_DEFER;
ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
if (ret < 0)
return ret;
- lvdscon->connector.encoder = renc;
+ ret = drm_panel_attach(rcon->panel, connector);
+ if (ret < 0)
+ return ret;
+
+ rcon->encoder = renc;
return 0;
}