[PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver
Inki Dae
inki.dae at samsung.com
Tue Dec 3 22:46:31 PST 2013
2013/12/3 Inki Dae <inki.dae at samsung.com>:
> Hi Sean,
>
>
> 2013/10/30 Sean Paul <seanpaul at chromium.org>:
>> This patch implements drm_connector directly in the dp driver, this will
>> allow us to move away from the exynos_drm_connector layer.
>>
>> Signed-off-by: Sean Paul <seanpaul at chromium.org>
>> ---
>>
>> Changes in v3:
>> - Added to the patchset
>>
>> drivers/gpu/drm/exynos/exynos_dp_core.c | 99 ++++++++++++++++++++++++++++++---
>> drivers/gpu/drm/exynos/exynos_dp_core.h | 4 ++
>> 2 files changed, 94 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
>> index 476d3b0..139ea15 100644
>> --- a/drivers/gpu/drm/exynos/exynos_dp_core.c
>> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
>> @@ -22,10 +22,15 @@
>> #include <video/of_videomode.h>
>>
>> #include <drm/drmP.h>
>> +#include <drm/drm_crtc.h>
>> +#include <drm/drm_crtc_helper.h>
>>
>> #include "exynos_drm_drv.h"
>> #include "exynos_dp_core.h"
>>
>> +#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \
>> + connector)
>> +
>> static int exynos_dp_init_dp(struct exynos_dp_device *dp)
>> {
>> exynos_dp_reset(dp);
>> @@ -896,21 +901,98 @@ static void exynos_dp_hotplug(struct work_struct *work)
>> dev_err(dp->dev, "unable to config video\n");
>> }
>>
>> -static bool exynos_dp_display_is_connected(struct exynos_drm_display *display)
>> +static enum drm_connector_status exynos_dp_detect(
>> + struct drm_connector *connector, bool force)
>> {
>> - return true;
>> + return connector_status_connected;
>
> No, eDP can be hot-plugged. Check if lcd panel is connected or not,
> and if connected then return connector_status_connected else
> connector_status_disconnected. See the interrupt handler.
>
>> }
>>
>> -static void *exynos_dp_get_panel(struct exynos_drm_display *display)
>> +static void exynos_dp_connector_destroy(struct drm_connector *connector)
>> {
>> - struct exynos_dp_device *dp = display->ctx;
>> +}
>> +
>> +static struct drm_connector_funcs exynos_dp_connector_funcs = {
>> + .dpms = drm_helper_connector_dpms,
>> + .fill_modes = drm_helper_probe_single_connector_modes,
>> + .detect = exynos_dp_detect,
>> + .destroy = exynos_dp_connector_destroy,
>> +};
>> +
>> +static int exynos_dp_get_modes(struct drm_connector *connector)
>> +{
>> + struct exynos_dp_device *dp = ctx_from_connector(connector);
>> + struct drm_display_mode *mode;
>> +
>> + mode = drm_mode_create(connector->dev);
>> + if (!mode) {
>> + DRM_ERROR("failed to create a new display mode.\n");
>> + return 0;
>> + }
>>
>> - return &dp->panel;
>> + drm_display_mode_from_videomode(&dp->panel.vm, mode);
>> + mode->width_mm = dp->panel.width_mm;
>> + mode->height_mm = dp->panel.height_mm;
>> + connector->display_info.width_mm = mode->width_mm;
>> + connector->display_info.height_mm = mode->height_mm;
>> +
>> + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
>> + drm_mode_set_name(mode);
>> + drm_mode_probed_add(connector, mode);
>> +
>> + return 1;
>> }
>>
>> -static int exynos_dp_check_mode(struct exynos_drm_display *display,
>> +static int exynos_dp_mode_valid(struct drm_connector *connector,
>> struct drm_display_mode *mode)
>> {
>> + return MODE_OK;
>> +}
>> +
>> +static struct drm_encoder *exynos_dp_best_encoder(
>> + struct drm_connector *connector)
>> +{
>> + struct exynos_dp_device *dp = ctx_from_connector(connector);
>> +
>> + return dp->encoder;
>
> eDP context doesn't need a encoder as its member. And you can get best
> encoder through connector->encoder.
>
Ah~ when drm is closed, connector->encoder could be NULL so it is
needed to connect again.
Sorry.
>> +}
>> +
>> +static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
>> + .get_modes = exynos_dp_get_modes,
>> + .mode_valid = exynos_dp_mode_valid,
>> + .best_encoder = exynos_dp_best_encoder,
>> +};
>> +
>> +static int exynos_dp_initialize(struct exynos_drm_display *display,
>> + struct drm_device *drm_dev)
>> +{
>> + struct exynos_dp_device *dp = display->ctx;
>> +
>> + dp->drm_dev = drm_dev;
>> +
>> + return 0;
>> +}
>> +
>> +static int exynos_dp_create_connector(struct exynos_drm_display *display,
>> + struct drm_encoder *encoder)
>> +{
>> + struct exynos_dp_device *dp = display->ctx;
>> + struct drm_connector *connector = &dp->connector;
>> + int ret;
>> +
>> + dp->encoder = encoder;
>
> Unnecessary line, Add connector->encoder = encoder instead.
Ignore it.
>
>> + connector->polled = DRM_CONNECTOR_POLL_HPD;
>> +
>> + ret = drm_connector_init(dp->drm_dev, connector,
>> + &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP);
>> + if (ret) {
>> + DRM_ERROR("Failed to initialize connector with drm\n");
>> + return ret;
>> + }
>> +
>> + drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
>> + drm_sysfs_connector_add(connector);
>> + drm_mode_connector_attach_encoder(connector, encoder);
>> +
>> return 0;
>> }
>>
>> @@ -986,9 +1068,8 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
>> }
>>
>> static struct exynos_drm_display_ops exynos_dp_display_ops = {
>> - .is_connected = exynos_dp_display_is_connected,
>> - .get_panel = exynos_dp_get_panel,
>> - .check_mode = exynos_dp_check_mode,
>> + .initialize = exynos_dp_initialize,
>> + .create_connector = exynos_dp_create_connector,
>> .dpms = exynos_dp_dpms,
>> };
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
>> index 0c67c19..da3fa7e 100644
>> --- a/drivers/gpu/drm/exynos/exynos_dp_core.h
>> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
>> @@ -13,6 +13,7 @@
>> #ifndef _EXYNOS_DP_CORE_H
>> #define _EXYNOS_DP_CORE_H
>>
>> +#include <drm/drm_crtc.h>
>> #include <drm/exynos_drm.h>
>> #include <video/exynos_dp.h>
>>
>> @@ -36,6 +37,9 @@ struct link_train {
>>
>> struct exynos_dp_device {
>> struct device *dev;
>> + struct drm_device *drm_dev;
>> + struct drm_connector connector;
>> + struct drm_encoder *encoder;
>
> I don't see why eDP context needs encoder pointer.
Ignore it.
>
>> struct clk *clock;
>> unsigned int irq;
>> void __iomem *reg_base;
>> --
>> 1.8.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
More information about the dri-devel
mailing list