From f70575805708cabdedea7498aaa3f710fde4d920 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 31 Jan 2024 03:29:01 +0000 Subject: [PATCH] add lvds1024*800 --- kernel/drivers/gpu/drm/omapdrm/omap_connector.c | 275 +++++++++++++----------------------------------------- 1 files changed, 66 insertions(+), 209 deletions(-) diff --git a/kernel/drivers/gpu/drm/omapdrm/omap_connector.c b/kernel/drivers/gpu/drm/omapdrm/omap_connector.c index 2ddb856..de95dc1 100644 --- a/kernel/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/kernel/drivers/gpu/drm/omapdrm/omap_connector.c @@ -1,23 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * Author: Rob Clark <rob@ti.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. */ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_crtc_helper.h> +#include <drm/drm_probe_helper.h> #include "omap_drv.h" @@ -29,204 +18,95 @@ struct omap_connector { struct drm_connector base; - struct omap_dss_device *dssdev; - bool hdmi_mode; + struct omap_dss_device *output; }; - -static void omap_connector_hpd_cb(void *cb_data, - enum drm_connector_status status) -{ - struct omap_connector *omap_connector = cb_data; - struct drm_connector *connector = &omap_connector->base; - struct drm_device *dev = connector->dev; - enum drm_connector_status old_status; - - mutex_lock(&dev->mode_config.mutex); - old_status = connector->status; - connector->status = status; - mutex_unlock(&dev->mode_config.mutex); - - if (old_status != status) - drm_kms_helper_hotplug_event(dev); -} - -bool omap_connector_get_hdmi_mode(struct drm_connector *connector) -{ - struct omap_connector *omap_connector = to_omap_connector(connector); - - return omap_connector->hdmi_mode; -} static enum drm_connector_status omap_connector_detect( struct drm_connector *connector, bool force) { - struct omap_connector *omap_connector = to_omap_connector(connector); - struct omap_dss_device *dssdev = omap_connector->dssdev; - struct omap_dss_driver *dssdrv = dssdev->driver; - enum drm_connector_status ret; - - if (dssdrv->detect) { - if (dssdrv->detect(dssdev)) - ret = connector_status_connected; - else - ret = connector_status_disconnected; - } else if (dssdev->type == OMAP_DISPLAY_TYPE_DPI || - dssdev->type == OMAP_DISPLAY_TYPE_DBI || - dssdev->type == OMAP_DISPLAY_TYPE_SDI || - dssdev->type == OMAP_DISPLAY_TYPE_DSI) { - ret = connector_status_connected; - } else { - ret = connector_status_unknown; - } - - VERB("%s: %d (force=%d)", omap_connector->dssdev->name, ret, force); - - return ret; + return connector_status_connected; } static void omap_connector_destroy(struct drm_connector *connector) { struct omap_connector *omap_connector = to_omap_connector(connector); - struct omap_dss_device *dssdev = omap_connector->dssdev; - DBG("%s", omap_connector->dssdev->name); - if (connector->polled == DRM_CONNECTOR_POLL_HPD && - dssdev->driver->unregister_hpd_cb) { - dssdev->driver->unregister_hpd_cb(dssdev); - } + DBG("%s", connector->name); + drm_connector_unregister(connector); drm_connector_cleanup(connector); + + omapdss_device_put(omap_connector->output); + kfree(omap_connector); - - omap_dss_put_device(dssdev); } - -#define MAX_EDID 512 static int omap_connector_get_modes(struct drm_connector *connector) { struct omap_connector *omap_connector = to_omap_connector(connector); - struct omap_dss_device *dssdev = omap_connector->dssdev; - struct omap_dss_driver *dssdrv = dssdev->driver; - struct drm_device *dev = connector->dev; - int n = 0; + struct omap_dss_device *dssdev = NULL; + struct omap_dss_device *d; - DBG("%s", omap_connector->dssdev->name); + DBG("%s", connector->name); - /* if display exposes EDID, then we parse that in the normal way to - * build table of supported modes.. otherwise (ie. fixed resolution - * LCD panels) we just return a single mode corresponding to the - * currently configured timings: + /* + * If the display pipeline reports modes (e.g. with a fixed resolution + * panel or an analog TV output), query it. */ - if (dssdrv->read_edid) { - void *edid = kzalloc(MAX_EDID, GFP_KERNEL); - - if (!edid) - return 0; - - if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) && - drm_edid_is_valid(edid)) { - drm_connector_update_edid_property( - connector, edid); - n = drm_add_edid_modes(connector, edid); - - omap_connector->hdmi_mode = - drm_detect_hdmi_monitor(edid); - } else { - drm_connector_update_edid_property( - connector, NULL); - } - - kfree(edid); - } else { - struct drm_display_mode *mode = drm_mode_create(dev); - struct videomode vm = {0}; - - if (!mode) - return 0; - - dssdrv->get_timings(dssdev, &vm); - - drm_display_mode_from_videomode(&vm, mode); - - mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; - drm_mode_set_name(mode); - drm_mode_probed_add(connector, mode); - - if (dssdrv->get_size) { - dssdrv->get_size(dssdev, - &connector->display_info.width_mm, - &connector->display_info.height_mm); - } - - n = 1; + for (d = omap_connector->output; d; d = d->next) { + if (d->ops_flags & OMAP_DSS_DEVICE_OP_MODES) + dssdev = d; } - return n; + if (dssdev) + return dssdev->ops->get_modes(dssdev, connector); + + /* We can't retrieve modes. The KMS core will add the default modes. */ + return 0; } -static int omap_connector_mode_valid(struct drm_connector *connector, +enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + int ret; + + drm_mode_copy(adjusted_mode, mode); + + for (; dssdev; dssdev = dssdev->next) { + if (!dssdev->ops || !dssdev->ops->check_timings) + continue; + + ret = dssdev->ops->check_timings(dssdev, adjusted_mode); + if (ret) + return MODE_BAD; + } + + return MODE_OK; +} + +static enum drm_mode_status omap_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct omap_connector *omap_connector = to_omap_connector(connector); - struct omap_dss_device *dssdev = omap_connector->dssdev; - struct omap_dss_driver *dssdrv = dssdev->driver; - struct videomode vm = {0}; - struct drm_device *dev = connector->dev; - struct drm_display_mode *new_mode; - int r, ret = MODE_BAD; + struct drm_display_mode new_mode = {}; + enum drm_mode_status status; - drm_display_mode_to_videomode(mode, &vm); - mode->vrefresh = drm_mode_vrefresh(mode); + status = omap_connector_mode_fixup(omap_connector->output, mode, + &new_mode); + if (status != MODE_OK) + goto done; - /* - * if the panel driver doesn't have a check_timings, it's most likely - * a fixed resolution panel, check if the timings match with the - * panel's timings - */ - if (dssdrv->check_timings) { - r = dssdrv->check_timings(dssdev, &vm); - } else { - struct videomode t = {0}; + /* Check if vrefresh is still valid. */ + if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(&new_mode)) + status = MODE_NOCLOCK; - dssdrv->get_timings(dssdev, &t); +done: + DBG("connector: mode %s: " DRM_MODE_FMT, + (status == MODE_OK) ? "valid" : "invalid", + DRM_MODE_ARG(mode)); - /* - * Ignore the flags, as we don't get them from - * drm_display_mode_to_videomode. - */ - t.flags = 0; - - if (memcmp(&vm, &t, sizeof(vm))) - r = -EINVAL; - else - r = 0; - } - - if (!r) { - /* check if vrefresh is still valid */ - new_mode = drm_mode_duplicate(dev, mode); - - if (!new_mode) - return MODE_BAD; - - new_mode->clock = vm.pixelclock / 1000; - new_mode->vrefresh = 0; - if (mode->vrefresh == drm_mode_vrefresh(new_mode)) - ret = MODE_OK; - drm_mode_destroy(dev, new_mode); - } - - DBG("connector: mode %s: " - "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", - (ret == MODE_OK) ? "valid" : "invalid", - mode->base.id, mode->name, mode->vrefresh, mode->clock, - mode->hdisplay, mode->hsync_start, - mode->hsync_end, mode->htotal, - mode->vdisplay, mode->vsync_start, - mode->vsync_end, mode->vtotal, mode->type, mode->flags); - - return ret; + return status; } static const struct drm_connector_funcs omap_connector_funcs = { @@ -245,51 +125,28 @@ /* initialize connector */ struct drm_connector *omap_connector_init(struct drm_device *dev, - int connector_type, struct omap_dss_device *dssdev, - struct drm_encoder *encoder) + struct omap_dss_device *output, + struct drm_encoder *encoder) { struct drm_connector *connector = NULL; struct omap_connector *omap_connector; - bool hpd_supported = false; - DBG("%s", dssdev->name); - - omap_dss_get_device(dssdev); + DBG("%s", output->name); omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL); if (!omap_connector) goto fail; - omap_connector->dssdev = dssdev; + omap_connector->output = omapdss_device_get(output); connector = &omap_connector->base; - - drm_connector_init(dev, connector, &omap_connector_funcs, - connector_type); - drm_connector_helper_add(connector, &omap_connector_helper_funcs); - - if (dssdev->driver->register_hpd_cb) { - int ret = dssdev->driver->register_hpd_cb(dssdev, - omap_connector_hpd_cb, - omap_connector); - if (!ret) - hpd_supported = true; - else if (ret != -ENOTSUPP) - DBG("%s: Failed to register HPD callback (%d).", - dssdev->name, ret); - } - - if (hpd_supported) - connector->polled = DRM_CONNECTOR_POLL_HPD; - else if (dssdev->driver->detect) - connector->polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - else - connector->polled = 0; - connector->interlace_allowed = 1; connector->doublescan_allowed = 0; + drm_connector_init(dev, connector, &omap_connector_funcs, + DRM_MODE_CONNECTOR_DSI); + drm_connector_helper_add(connector, &omap_connector_helper_funcs); + return connector; fail: -- Gitblit v1.6.2