linux/drivers/gpu/drm/sun4i/sun4i_tcon.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2015 Free Electrons
 * Copyright (C) 2015 NextThing Co
 *
 * Maxime Ripard <[email protected]>
 */

#include <linux/component.h>
#include <linux/ioport.h>
#include <linux/media-bus-format.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>

#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
#include <drm/drm_modes.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>

#include <uapi/drm/drm_mode.h>

#include "sun4i_crtc.h"
#include "sun4i_drv.h"
#include "sun4i_lvds.h"
#include "sun4i_rgb.h"
#include "sun4i_tcon.h"
#include "sun6i_mipi_dsi.h"
#include "sun4i_tcon_dclk.h"
#include "sun8i_tcon_top.h"
#include "sunxi_engine.h"

static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
{}

static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
{}

static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
					  bool enabled)
{}

static void sun4i_tcon_setup_lvds_phy(struct sun4i_tcon *tcon,
				      const struct drm_encoder *encoder)
{}

static void sun6i_tcon_setup_lvds_phy(struct sun4i_tcon *tcon,
				      const struct drm_encoder *encoder)
{}

static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
				       const struct drm_encoder *encoder,
				       bool enabled)
{}

void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
			   const struct drm_encoder *encoder,
			   bool enabled)
{}

void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
{}
EXPORT_SYMBOL();

/*
 * This function is a helper for TCON output muxing. The TCON output
 * muxing control register in earlier SoCs (without the TCON TOP block)
 * are located in TCON0. This helper returns a pointer to TCON0's
 * sun4i_tcon structure, or NULL if not found.
 */
static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
{}

static void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
			       const struct drm_encoder *encoder)
{}

static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
				    int channel)
{}

static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
					   const struct drm_connector *connector)
{}

static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
				     const struct drm_encoder *encoder,
				     const struct drm_display_mode *mode)
{}

static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
				      const struct drm_encoder *encoder,
				      const struct drm_display_mode *mode)
{}

static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
				     const struct drm_encoder *encoder,
				     const struct drm_display_mode *mode)
{}

static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
				 const struct drm_display_mode *mode)
{}

void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
			 const struct drm_encoder *encoder,
			 const struct drm_display_mode *mode)
{}
EXPORT_SYMBOL();

static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
					struct sun4i_crtc *scrtc)
{}

static irqreturn_t sun4i_tcon_handler(int irq, void *private)
{}

static int sun4i_tcon_init_clocks(struct device *dev,
				  struct sun4i_tcon *tcon)
{}

static int sun4i_tcon_init_irq(struct device *dev,
			       struct sun4i_tcon *tcon)
{}

static const struct regmap_config sun4i_tcon_regmap_config =;

static int sun4i_tcon_init_regmap(struct device *dev,
				  struct sun4i_tcon *tcon)
{}

/*
 * On SoCs with the old display pipeline design (Display Engine 1.0),
 * the TCON is always tied to just one backend. Hence we can traverse
 * the of_graph upwards to find the backend our tcon is connected to,
 * and take its ID as our own.
 *
 * We can either identify backends from their compatible strings, which
 * means maintaining a large list of them. Or, since the backend is
 * registered and binded before the TCON, we can just go through the
 * list of registered backends and compare the device node.
 *
 * As the structures now store engines instead of backends, here this
 * function in fact searches the corresponding engine, and the ID is
 * requested via the get_id function of the engine.
 */
static struct sunxi_engine *
sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
				struct device_node *node,
				u32 port_id)
{}

/*
 * The device tree binding says that the remote endpoint ID of any
 * connection between components, up to and including the TCON, of
 * the display pipeline should be equal to the actual ID of the local
 * component. Thus we can look at any one of the input connections of
 * the TCONs, and use that connection's remote endpoint ID as our own.
 *
 * Since the user of this function already finds the input port,
 * the port is passed in directly without further checks.
 */
static int sun4i_tcon_of_get_id_from_port(struct device_node *port)
{}

/*
 * Once we know the TCON's id, we can look through the list of
 * engines to find a matching one. We assume all engines have
 * been probed and added to the list.
 */
static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
							int id)
{}

static bool sun4i_tcon_connected_to_tcon_top(struct device_node *node)
{}

static int sun4i_tcon_get_index(struct sun4i_drv *drv)
{}

/*
 * On SoCs with the old display pipeline design (Display Engine 1.0),
 * we assumed the TCON was always tied to just one backend. However
 * this proved not to be the case. On the A31, the TCON can select
 * either backend as its source. On the A20 (and likely on the A10),
 * the backend can choose which TCON to output to.
 *
 * The device tree binding says that the remote endpoint ID of any
 * connection between components, up to and including the TCON, of
 * the display pipeline should be equal to the actual ID of the local
 * component. Thus we should be able to look at any one of the input
 * connections of the TCONs, and use that connection's remote endpoint
 * ID as our own.
 *
 * However  the connections between the backend and TCON were assumed
 * to be always singular, and their endpoit IDs were all incorrectly
 * set to 0. This means for these old device trees, we cannot just look
 * up the remote endpoint ID of a TCON input endpoint. TCON1 would be
 * incorrectly identified as TCON0.
 *
 * This function first checks if the TCON node has 2 input endpoints.
 * If so, then the device tree is a corrected version, and it will use
 * sun4i_tcon_of_get_id() and sun4i_tcon_get_engine_by_id() from above
 * to fetch the ID and engine directly. If not, then it is likely an
 * old device trees, where the endpoint IDs were incorrect, but did not
 * have endpoint connections between the backend and TCON across
 * different display pipelines. It will fall back to the old method of
 * traversing the  of_graph to try and find a matching engine by device
 * node.
 *
 * In the case of single display pipeline device trees, either method
 * works.
 */
static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
						   struct device_node *node)
{}

static int sun4i_tcon_bind(struct device *dev, struct device *master,
			   void *data)
{}

static void sun4i_tcon_unbind(struct device *dev, struct device *master,
			      void *data)
{}

static const struct component_ops sun4i_tcon_ops =;

static int sun4i_tcon_probe(struct platform_device *pdev)
{}

static void sun4i_tcon_remove(struct platform_device *pdev)
{}

/* platform specific TCON muxing callbacks */
static int sun4i_a10_tcon_set_mux(struct sun4i_tcon *tcon,
				  const struct drm_encoder *encoder)
{}

static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
				  const struct drm_encoder *encoder)
{}

static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
			      const struct drm_encoder *encoder)
{}

static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
				     const struct drm_encoder *encoder)
{}

static const struct sun4i_tcon_quirks sun4i_a10_quirks =;

static const struct sun4i_tcon_quirks sun5i_a13_quirks =;

static const struct sun4i_tcon_quirks sun6i_a31_quirks =;

static const struct sun4i_tcon_quirks sun6i_a31s_quirks =;

static const struct sun4i_tcon_quirks sun7i_a20_tcon0_quirks =;

static const struct sun4i_tcon_quirks sun7i_a20_quirks =;

static const struct sun4i_tcon_quirks sun8i_a33_quirks =;

static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks =;

static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks =;

static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks =;

static const struct sun4i_tcon_quirks sun8i_v3s_quirks =;

static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks =;

static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks =;

static const struct sun4i_tcon_quirks sun20i_d1_lcd_quirks =;

/* sun4i_drv uses this list to check if a device node is a TCON */
const struct of_device_id sun4i_tcon_of_table[] =;
MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
EXPORT_SYMBOL();

static struct platform_driver sun4i_tcon_platform_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();