cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

omap_encoder.c (4077B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
      4 * Author: Rob Clark <rob@ti.com>
      5 */
      6
      7#include <linux/list.h>
      8
      9#include <drm/drm_bridge.h>
     10#include <drm/drm_crtc.h>
     11#include <drm/drm_modeset_helper_vtables.h>
     12#include <drm/drm_edid.h>
     13
     14#include "omap_drv.h"
     15
     16/*
     17 * encoder funcs
     18 */
     19
     20#define to_omap_encoder(x) container_of(x, struct omap_encoder, base)
     21
     22/* The encoder and connector both map to same dssdev.. the encoder
     23 * handles the 'active' parts, ie. anything the modifies the state
     24 * of the hw, and the connector handles the 'read-only' parts, like
     25 * detecting connection and reading edid.
     26 */
     27struct omap_encoder {
     28	struct drm_encoder base;
     29	struct omap_dss_device *output;
     30};
     31
     32static void omap_encoder_destroy(struct drm_encoder *encoder)
     33{
     34	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
     35
     36	drm_encoder_cleanup(encoder);
     37	kfree(omap_encoder);
     38}
     39
     40static const struct drm_encoder_funcs omap_encoder_funcs = {
     41	.destroy = omap_encoder_destroy,
     42};
     43
     44static void omap_encoder_update_videomode_flags(struct videomode *vm,
     45						u32 bus_flags)
     46{
     47	if (!(vm->flags & (DISPLAY_FLAGS_DE_LOW |
     48			   DISPLAY_FLAGS_DE_HIGH))) {
     49		if (bus_flags & DRM_BUS_FLAG_DE_LOW)
     50			vm->flags |= DISPLAY_FLAGS_DE_LOW;
     51		else if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
     52			vm->flags |= DISPLAY_FLAGS_DE_HIGH;
     53	}
     54
     55	if (!(vm->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE |
     56			   DISPLAY_FLAGS_PIXDATA_NEGEDGE))) {
     57		if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
     58			vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
     59		else if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
     60			vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
     61	}
     62
     63	if (!(vm->flags & (DISPLAY_FLAGS_SYNC_POSEDGE |
     64			   DISPLAY_FLAGS_SYNC_NEGEDGE))) {
     65		if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE)
     66			vm->flags |= DISPLAY_FLAGS_SYNC_POSEDGE;
     67		else if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE)
     68			vm->flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
     69	}
     70}
     71
     72static void omap_encoder_mode_set(struct drm_encoder *encoder,
     73				  struct drm_display_mode *mode,
     74				  struct drm_display_mode *adjusted_mode)
     75{
     76	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
     77	struct omap_dss_device *output = omap_encoder->output;
     78	struct drm_device *dev = encoder->dev;
     79	struct drm_connector *connector;
     80	struct drm_bridge *bridge;
     81	struct videomode vm = { 0 };
     82	u32 bus_flags;
     83
     84	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
     85		if (connector->encoder == encoder)
     86			break;
     87	}
     88
     89	drm_display_mode_to_videomode(adjusted_mode, &vm);
     90
     91	/*
     92	 * HACK: This fixes the vm flags.
     93	 * struct drm_display_mode does not contain the VSYNC/HSYNC/DE flags and
     94	 * they get lost when converting back and forth between struct
     95	 * drm_display_mode and struct videomode. The hack below goes and
     96	 * fetches the missing flags.
     97	 *
     98	 * A better solution is to use DRM's bus-flags through the whole driver.
     99	 */
    100	for (bridge = output->bridge; bridge;
    101	     bridge = drm_bridge_get_next_bridge(bridge)) {
    102		if (!bridge->timings)
    103			continue;
    104
    105		bus_flags = bridge->timings->input_bus_flags;
    106		omap_encoder_update_videomode_flags(&vm, bus_flags);
    107	}
    108
    109	bus_flags = connector->display_info.bus_flags;
    110	omap_encoder_update_videomode_flags(&vm, bus_flags);
    111
    112	/* Set timings for all devices in the display pipeline. */
    113	dss_mgr_set_timings(output, &vm);
    114}
    115
    116static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
    117	.mode_set = omap_encoder_mode_set,
    118};
    119
    120/* initialize encoder */
    121struct drm_encoder *omap_encoder_init(struct drm_device *dev,
    122				      struct omap_dss_device *output)
    123{
    124	struct drm_encoder *encoder = NULL;
    125	struct omap_encoder *omap_encoder;
    126
    127	omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
    128	if (!omap_encoder)
    129		goto fail;
    130
    131	omap_encoder->output = output;
    132
    133	encoder = &omap_encoder->base;
    134
    135	drm_encoder_init(dev, encoder, &omap_encoder_funcs,
    136			 DRM_MODE_ENCODER_TMDS, NULL);
    137	drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
    138
    139	return encoder;
    140
    141fail:
    142	if (encoder)
    143		omap_encoder_destroy(encoder);
    144
    145	return NULL;
    146}