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

sun4i_tcon.c (45463B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2015 Free Electrons
      4 * Copyright (C) 2015 NextThing Co
      5 *
      6 * Maxime Ripard <maxime.ripard@free-electrons.com>
      7 */
      8
      9#include <linux/component.h>
     10#include <linux/ioport.h>
     11#include <linux/module.h>
     12#include <linux/of_address.h>
     13#include <linux/of_device.h>
     14#include <linux/of_irq.h>
     15#include <linux/regmap.h>
     16#include <linux/reset.h>
     17
     18#include <drm/drm_atomic_helper.h>
     19#include <drm/drm_bridge.h>
     20#include <drm/drm_connector.h>
     21#include <drm/drm_crtc.h>
     22#include <drm/drm_encoder.h>
     23#include <drm/drm_modes.h>
     24#include <drm/drm_of.h>
     25#include <drm/drm_panel.h>
     26#include <drm/drm_print.h>
     27#include <drm/drm_probe_helper.h>
     28#include <drm/drm_vblank.h>
     29
     30#include <uapi/drm/drm_mode.h>
     31
     32#include "sun4i_crtc.h"
     33#include "sun4i_dotclock.h"
     34#include "sun4i_drv.h"
     35#include "sun4i_lvds.h"
     36#include "sun4i_rgb.h"
     37#include "sun4i_tcon.h"
     38#include "sun6i_mipi_dsi.h"
     39#include "sun8i_tcon_top.h"
     40#include "sunxi_engine.h"
     41
     42static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
     43{
     44	struct drm_connector *connector;
     45	struct drm_connector_list_iter iter;
     46
     47	drm_connector_list_iter_begin(encoder->dev, &iter);
     48	drm_for_each_connector_iter(connector, &iter)
     49		if (connector->encoder == encoder) {
     50			drm_connector_list_iter_end(&iter);
     51			return connector;
     52		}
     53	drm_connector_list_iter_end(&iter);
     54
     55	return NULL;
     56}
     57
     58static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
     59{
     60	struct drm_connector *connector;
     61	struct drm_display_info *info;
     62
     63	connector = sun4i_tcon_get_connector(encoder);
     64	if (!connector)
     65		return -EINVAL;
     66
     67	info = &connector->display_info;
     68	if (info->num_bus_formats != 1)
     69		return -EINVAL;
     70
     71	switch (info->bus_formats[0]) {
     72	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
     73		return 18;
     74
     75	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
     76	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
     77		return 24;
     78	}
     79
     80	return -EINVAL;
     81}
     82
     83static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
     84					  bool enabled)
     85{
     86	struct clk *clk;
     87
     88	switch (channel) {
     89	case 0:
     90		WARN_ON(!tcon->quirks->has_channel_0);
     91		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
     92				   SUN4I_TCON0_CTL_TCON_ENABLE,
     93				   enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
     94		clk = tcon->dclk;
     95		break;
     96	case 1:
     97		WARN_ON(!tcon->quirks->has_channel_1);
     98		regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
     99				   SUN4I_TCON1_CTL_TCON_ENABLE,
    100				   enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
    101		clk = tcon->sclk1;
    102		break;
    103	default:
    104		DRM_WARN("Unknown channel... doing nothing\n");
    105		return;
    106	}
    107
    108	if (enabled) {
    109		clk_prepare_enable(clk);
    110		clk_rate_exclusive_get(clk);
    111	} else {
    112		clk_rate_exclusive_put(clk);
    113		clk_disable_unprepare(clk);
    114	}
    115}
    116
    117static void sun4i_tcon_setup_lvds_phy(struct sun4i_tcon *tcon,
    118				      const struct drm_encoder *encoder)
    119{
    120	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
    121		     SUN4I_TCON0_LVDS_ANA0_CK_EN |
    122		     SUN4I_TCON0_LVDS_ANA0_REG_V |
    123		     SUN4I_TCON0_LVDS_ANA0_REG_C |
    124		     SUN4I_TCON0_LVDS_ANA0_EN_MB |
    125		     SUN4I_TCON0_LVDS_ANA0_PD |
    126		     SUN4I_TCON0_LVDS_ANA0_DCHS);
    127
    128	udelay(2); /* delay at least 1200 ns */
    129	regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
    130			   SUN4I_TCON0_LVDS_ANA1_INIT,
    131			   SUN4I_TCON0_LVDS_ANA1_INIT);
    132	udelay(1); /* delay at least 120 ns */
    133	regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
    134			   SUN4I_TCON0_LVDS_ANA1_UPDATE,
    135			   SUN4I_TCON0_LVDS_ANA1_UPDATE);
    136	regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
    137			   SUN4I_TCON0_LVDS_ANA0_EN_MB,
    138			   SUN4I_TCON0_LVDS_ANA0_EN_MB);
    139}
    140
    141static void sun6i_tcon_setup_lvds_phy(struct sun4i_tcon *tcon,
    142				      const struct drm_encoder *encoder)
    143{
    144	u8 val;
    145
    146	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
    147		     SUN6I_TCON0_LVDS_ANA0_C(2) |
    148		     SUN6I_TCON0_LVDS_ANA0_V(3) |
    149		     SUN6I_TCON0_LVDS_ANA0_PD(2) |
    150		     SUN6I_TCON0_LVDS_ANA0_EN_LDO);
    151	udelay(2);
    152
    153	regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
    154			   SUN6I_TCON0_LVDS_ANA0_EN_MB,
    155			   SUN6I_TCON0_LVDS_ANA0_EN_MB);
    156	udelay(2);
    157
    158	regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
    159			   SUN6I_TCON0_LVDS_ANA0_EN_DRVC,
    160			   SUN6I_TCON0_LVDS_ANA0_EN_DRVC);
    161
    162	if (sun4i_tcon_get_pixel_depth(encoder) == 18)
    163		val = 7;
    164	else
    165		val = 0xf;
    166
    167	regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
    168			  SUN6I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
    169			  SUN6I_TCON0_LVDS_ANA0_EN_DRVD(val));
    170}
    171
    172static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
    173				       const struct drm_encoder *encoder,
    174				       bool enabled)
    175{
    176	if (enabled) {
    177		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
    178				   SUN4I_TCON0_LVDS_IF_EN,
    179				   SUN4I_TCON0_LVDS_IF_EN);
    180		if (tcon->quirks->setup_lvds_phy)
    181			tcon->quirks->setup_lvds_phy(tcon, encoder);
    182	} else {
    183		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
    184				   SUN4I_TCON0_LVDS_IF_EN, 0);
    185	}
    186}
    187
    188void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
    189			   const struct drm_encoder *encoder,
    190			   bool enabled)
    191{
    192	bool is_lvds = false;
    193	int channel;
    194
    195	switch (encoder->encoder_type) {
    196	case DRM_MODE_ENCODER_LVDS:
    197		is_lvds = true;
    198		fallthrough;
    199	case DRM_MODE_ENCODER_DSI:
    200	case DRM_MODE_ENCODER_NONE:
    201		channel = 0;
    202		break;
    203	case DRM_MODE_ENCODER_TMDS:
    204	case DRM_MODE_ENCODER_TVDAC:
    205		channel = 1;
    206		break;
    207	default:
    208		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
    209		return;
    210	}
    211
    212	if (is_lvds && !enabled)
    213		sun4i_tcon_lvds_set_status(tcon, encoder, false);
    214
    215	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
    216			   SUN4I_TCON_GCTL_TCON_ENABLE,
    217			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
    218
    219	if (is_lvds && enabled)
    220		sun4i_tcon_lvds_set_status(tcon, encoder, true);
    221
    222	sun4i_tcon_channel_set_status(tcon, channel, enabled);
    223}
    224
    225void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
    226{
    227	u32 mask, val = 0;
    228
    229	DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis");
    230
    231	mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) |
    232		SUN4I_TCON_GINT0_VBLANK_ENABLE(1) |
    233		SUN4I_TCON_GINT0_TCON0_TRI_FINISH_ENABLE;
    234
    235	if (enable)
    236		val = mask;
    237
    238	regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val);
    239}
    240EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
    241
    242/*
    243 * This function is a helper for TCON output muxing. The TCON output
    244 * muxing control register in earlier SoCs (without the TCON TOP block)
    245 * are located in TCON0. This helper returns a pointer to TCON0's
    246 * sun4i_tcon structure, or NULL if not found.
    247 */
    248static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
    249{
    250	struct sun4i_drv *drv = drm->dev_private;
    251	struct sun4i_tcon *tcon;
    252
    253	list_for_each_entry(tcon, &drv->tcon_list, list)
    254		if (tcon->id == 0)
    255			return tcon;
    256
    257	dev_warn(drm->dev,
    258		 "TCON0 not found, display output muxing may not work\n");
    259
    260	return NULL;
    261}
    262
    263static void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
    264			       const struct drm_encoder *encoder)
    265{
    266	int ret = -ENOTSUPP;
    267
    268	if (tcon->quirks->set_mux)
    269		ret = tcon->quirks->set_mux(tcon, encoder);
    270
    271	DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
    272			 encoder->name, encoder->crtc->name, ret);
    273}
    274
    275static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
    276				    int channel)
    277{
    278	int delay = mode->vtotal - mode->vdisplay;
    279
    280	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
    281		delay /= 2;
    282
    283	if (channel == 1)
    284		delay -= 2;
    285
    286	delay = min(delay, 30);
    287
    288	DRM_DEBUG_DRIVER("TCON %d clock delay %u\n", channel, delay);
    289
    290	return delay;
    291}
    292
    293static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
    294					const struct drm_display_mode *mode)
    295{
    296	/* Configure the dot clock */
    297	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
    298
    299	/* Set the resolution */
    300	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
    301		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
    302		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
    303}
    304
    305static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
    306					   const struct drm_connector *connector)
    307{
    308	u32 bus_format = 0;
    309	u32 val = 0;
    310
    311	/* XXX Would this ever happen? */
    312	if (!connector)
    313		return;
    314
    315	/*
    316	 * FIXME: Undocumented bits
    317	 *
    318	 * The whole dithering process and these parameters are not
    319	 * explained in the vendor documents or BSP kernel code.
    320	 */
    321	regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PR_REG, 0x11111111);
    322	regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PG_REG, 0x11111111);
    323	regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PB_REG, 0x11111111);
    324	regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LR_REG, 0x11111111);
    325	regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LG_REG, 0x11111111);
    326	regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LB_REG, 0x11111111);
    327	regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL0_REG, 0x01010000);
    328	regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL1_REG, 0x15151111);
    329	regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL2_REG, 0x57575555);
    330	regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL3_REG, 0x7f7f7777);
    331
    332	/* Do dithering if panel only supports 6 bits per color */
    333	if (connector->display_info.bpc == 6)
    334		val |= SUN4I_TCON0_FRM_CTL_EN;
    335
    336	if (connector->display_info.num_bus_formats == 1)
    337		bus_format = connector->display_info.bus_formats[0];
    338
    339	/* Check the connection format */
    340	switch (bus_format) {
    341	case MEDIA_BUS_FMT_RGB565_1X16:
    342		/* R and B components are only 5 bits deep */
    343		val |= SUN4I_TCON0_FRM_CTL_MODE_R;
    344		val |= SUN4I_TCON0_FRM_CTL_MODE_B;
    345		fallthrough;
    346	case MEDIA_BUS_FMT_RGB666_1X18:
    347	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
    348		/* Fall through: enable dithering */
    349		val |= SUN4I_TCON0_FRM_CTL_EN;
    350		break;
    351	}
    352
    353	/* Write dithering settings */
    354	regmap_write(tcon->regs, SUN4I_TCON_FRM_CTL_REG, val);
    355}
    356
    357static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
    358				     const struct drm_encoder *encoder,
    359				     const struct drm_display_mode *mode)
    360{
    361	/* TODO support normal CPU interface modes */
    362	struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
    363	struct mipi_dsi_device *device = dsi->device;
    364	u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
    365	u8 lanes = device->lanes;
    366	u32 block_space, start_delay;
    367	u32 tcon_div;
    368
    369	tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
    370	tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
    371
    372	sun4i_tcon0_mode_set_common(tcon, mode);
    373
    374	/* Set dithering if needed */
    375	sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
    376
    377	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
    378			   SUN4I_TCON0_CTL_IF_MASK,
    379			   SUN4I_TCON0_CTL_IF_8080);
    380
    381	regmap_write(tcon->regs, SUN4I_TCON_ECC_FIFO_REG,
    382		     SUN4I_TCON_ECC_FIFO_EN);
    383
    384	regmap_write(tcon->regs, SUN4I_TCON0_CPU_IF_REG,
    385		     SUN4I_TCON0_CPU_IF_MODE_DSI |
    386		     SUN4I_TCON0_CPU_IF_TRI_FIFO_FLUSH |
    387		     SUN4I_TCON0_CPU_IF_TRI_FIFO_EN |
    388		     SUN4I_TCON0_CPU_IF_TRI_EN);
    389
    390	/*
    391	 * This looks suspicious, but it works...
    392	 *
    393	 * The datasheet says that this should be set higher than 20 *
    394	 * pixel cycle, but it's not clear what a pixel cycle is.
    395	 */
    396	regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
    397	tcon_div &= GENMASK(6, 0);
    398	block_space = mode->htotal * bpp / (tcon_div * lanes);
    399	block_space -= mode->hdisplay + 40;
    400
    401	regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
    402		     SUN4I_TCON0_CPU_TRI0_BLOCK_SPACE(block_space) |
    403		     SUN4I_TCON0_CPU_TRI0_BLOCK_SIZE(mode->hdisplay));
    404
    405	regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI1_REG,
    406		     SUN4I_TCON0_CPU_TRI1_BLOCK_NUM(mode->vdisplay));
    407
    408	start_delay = (mode->crtc_vtotal - mode->crtc_vdisplay - 10 - 1);
    409	start_delay = start_delay * mode->crtc_htotal * 149;
    410	start_delay = start_delay / (mode->crtc_clock / 1000) / 8;
    411	regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI2_REG,
    412		     SUN4I_TCON0_CPU_TRI2_TRANS_START_SET(10) |
    413		     SUN4I_TCON0_CPU_TRI2_START_DELAY(start_delay));
    414
    415	/*
    416	 * The Allwinner BSP has a comment that the period should be
    417	 * the display clock * 15, but uses an hardcoded 3000...
    418	 */
    419	regmap_write(tcon->regs, SUN4I_TCON_SAFE_PERIOD_REG,
    420		     SUN4I_TCON_SAFE_PERIOD_NUM(3000) |
    421		     SUN4I_TCON_SAFE_PERIOD_MODE(3));
    422
    423	/* Enable the output on the pins */
    424	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG,
    425		     0xe0000000);
    426}
    427
    428static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
    429				      const struct drm_encoder *encoder,
    430				      const struct drm_display_mode *mode)
    431{
    432	unsigned int bp;
    433	u8 clk_delay;
    434	u32 reg, val = 0;
    435
    436	WARN_ON(!tcon->quirks->has_channel_0);
    437
    438	tcon->dclk_min_div = 7;
    439	tcon->dclk_max_div = 7;
    440	sun4i_tcon0_mode_set_common(tcon, mode);
    441
    442	/* Set dithering if needed */
    443	sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
    444
    445	/* Adjust clock delay */
    446	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
    447	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
    448			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
    449			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
    450
    451	/*
    452	 * This is called a backporch in the register documentation,
    453	 * but it really is the back porch + hsync
    454	 */
    455	bp = mode->crtc_htotal - mode->crtc_hsync_start;
    456	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
    457			 mode->crtc_htotal, bp);
    458
    459	/* Set horizontal display timings */
    460	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
    461		     SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
    462		     SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
    463
    464	/*
    465	 * This is called a backporch in the register documentation,
    466	 * but it really is the back porch + hsync
    467	 */
    468	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
    469	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
    470			 mode->crtc_vtotal, bp);
    471
    472	/* Set vertical display timings */
    473	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
    474		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
    475		     SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
    476
    477	reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0;
    478	if (sun4i_tcon_get_pixel_depth(encoder) == 24)
    479		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
    480	else
    481		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
    482
    483	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
    484
    485	/* Setup the polarity of the various signals */
    486	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
    487		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
    488
    489	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
    490		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
    491
    492	regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
    493
    494	/* Map output pins to channel 0 */
    495	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
    496			   SUN4I_TCON_GCTL_IOMAP_MASK,
    497			   SUN4I_TCON_GCTL_IOMAP_TCON0);
    498
    499	/* Enable the output on the pins */
    500	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
    501}
    502
    503static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
    504				     const struct drm_encoder *encoder,
    505				     const struct drm_display_mode *mode)
    506{
    507	struct drm_connector *connector = sun4i_tcon_get_connector(encoder);
    508	const struct drm_display_info *info = &connector->display_info;
    509	unsigned int bp, hsync, vsync;
    510	u8 clk_delay;
    511	u32 val = 0;
    512
    513	WARN_ON(!tcon->quirks->has_channel_0);
    514
    515	tcon->dclk_min_div = tcon->quirks->dclk_min_div;
    516	tcon->dclk_max_div = 127;
    517	sun4i_tcon0_mode_set_common(tcon, mode);
    518
    519	/* Set dithering if needed */
    520	sun4i_tcon0_mode_set_dithering(tcon, connector);
    521
    522	/* Adjust clock delay */
    523	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
    524	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
    525			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
    526			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
    527
    528	/*
    529	 * This is called a backporch in the register documentation,
    530	 * but it really is the back porch + hsync
    531	 */
    532	bp = mode->crtc_htotal - mode->crtc_hsync_start;
    533	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
    534			 mode->crtc_htotal, bp);
    535
    536	/* Set horizontal display timings */
    537	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
    538		     SUN4I_TCON0_BASIC1_H_TOTAL(mode->crtc_htotal) |
    539		     SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
    540
    541	/*
    542	 * This is called a backporch in the register documentation,
    543	 * but it really is the back porch + hsync
    544	 */
    545	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
    546	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
    547			 mode->crtc_vtotal, bp);
    548
    549	/* Set vertical display timings */
    550	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
    551		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
    552		     SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
    553
    554	/* Set Hsync and Vsync length */
    555	hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
    556	vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
    557	DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
    558	regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG,
    559		     SUN4I_TCON0_BASIC3_V_SYNC(vsync) |
    560		     SUN4I_TCON0_BASIC3_H_SYNC(hsync));
    561
    562	/* Setup the polarity of the various signals */
    563	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
    564		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
    565
    566	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
    567		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
    568
    569	if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
    570		val |= SUN4I_TCON0_IO_POL_DE_NEGATIVE;
    571
    572	if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
    573		val |= SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE;
    574
    575	regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
    576			   SUN4I_TCON0_IO_POL_HSYNC_POSITIVE |
    577			   SUN4I_TCON0_IO_POL_VSYNC_POSITIVE |
    578			   SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE |
    579			   SUN4I_TCON0_IO_POL_DE_NEGATIVE,
    580			   val);
    581
    582	/* Map output pins to channel 0 */
    583	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
    584			   SUN4I_TCON_GCTL_IOMAP_MASK,
    585			   SUN4I_TCON_GCTL_IOMAP_TCON0);
    586
    587	/* Enable the output on the pins */
    588	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
    589}
    590
    591static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
    592				 const struct drm_display_mode *mode)
    593{
    594	unsigned int bp, hsync, vsync, vtotal;
    595	u8 clk_delay;
    596	u32 val;
    597
    598	WARN_ON(!tcon->quirks->has_channel_1);
    599
    600	/* Configure the dot clock */
    601	clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
    602
    603	/* Adjust clock delay */
    604	clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
    605	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
    606			   SUN4I_TCON1_CTL_CLK_DELAY_MASK,
    607			   SUN4I_TCON1_CTL_CLK_DELAY(clk_delay));
    608
    609	/* Set interlaced mode */
    610	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
    611		val = SUN4I_TCON1_CTL_INTERLACE_ENABLE;
    612	else
    613		val = 0;
    614	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
    615			   SUN4I_TCON1_CTL_INTERLACE_ENABLE,
    616			   val);
    617
    618	/* Set the input resolution */
    619	regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG,
    620		     SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) |
    621		     SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay));
    622
    623	/* Set the upscaling resolution */
    624	regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG,
    625		     SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) |
    626		     SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay));
    627
    628	/* Set the output resolution */
    629	regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG,
    630		     SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) |
    631		     SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay));
    632
    633	/* Set horizontal display timings */
    634	bp = mode->crtc_htotal - mode->crtc_hsync_start;
    635	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
    636			 mode->htotal, bp);
    637	regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG,
    638		     SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) |
    639		     SUN4I_TCON1_BASIC3_H_BACKPORCH(bp));
    640
    641	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
    642	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
    643			 mode->crtc_vtotal, bp);
    644
    645	/*
    646	 * The vertical resolution needs to be doubled in all
    647	 * cases. We could use crtc_vtotal and always multiply by two,
    648	 * but that leads to a rounding error in interlace when vtotal
    649	 * is odd.
    650	 *
    651	 * This happens with TV's PAL for example, where vtotal will
    652	 * be 625, crtc_vtotal 312, and thus crtc_vtotal * 2 will be
    653	 * 624, which apparently confuses the hardware.
    654	 *
    655	 * To work around this, we will always use vtotal, and
    656	 * multiply by two only if we're not in interlace.
    657	 */
    658	vtotal = mode->vtotal;
    659	if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
    660		vtotal = vtotal * 2;
    661
    662	/* Set vertical display timings */
    663	regmap_write(tcon->regs, SUN4I_TCON1_BASIC4_REG,
    664		     SUN4I_TCON1_BASIC4_V_TOTAL(vtotal) |
    665		     SUN4I_TCON1_BASIC4_V_BACKPORCH(bp));
    666
    667	/* Set Hsync and Vsync length */
    668	hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
    669	vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
    670	DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
    671	regmap_write(tcon->regs, SUN4I_TCON1_BASIC5_REG,
    672		     SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
    673		     SUN4I_TCON1_BASIC5_H_SYNC(hsync));
    674
    675	/* Setup the polarity of multiple signals */
    676	if (tcon->quirks->polarity_in_ch0) {
    677		val = 0;
    678
    679		if (mode->flags & DRM_MODE_FLAG_PHSYNC)
    680			val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
    681
    682		if (mode->flags & DRM_MODE_FLAG_PVSYNC)
    683			val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
    684
    685		regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
    686	} else {
    687		/* according to vendor driver, this bit must be always set */
    688		val = SUN4I_TCON1_IO_POL_UNKNOWN;
    689
    690		if (mode->flags & DRM_MODE_FLAG_PHSYNC)
    691			val |= SUN4I_TCON1_IO_POL_HSYNC_POSITIVE;
    692
    693		if (mode->flags & DRM_MODE_FLAG_PVSYNC)
    694			val |= SUN4I_TCON1_IO_POL_VSYNC_POSITIVE;
    695
    696		regmap_write(tcon->regs, SUN4I_TCON1_IO_POL_REG, val);
    697	}
    698
    699	/* Map output pins to channel 1 */
    700	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
    701			   SUN4I_TCON_GCTL_IOMAP_MASK,
    702			   SUN4I_TCON_GCTL_IOMAP_TCON1);
    703}
    704
    705void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
    706			 const struct drm_encoder *encoder,
    707			 const struct drm_display_mode *mode)
    708{
    709	switch (encoder->encoder_type) {
    710	case DRM_MODE_ENCODER_DSI:
    711		/* DSI is tied to special case of CPU interface */
    712		sun4i_tcon0_mode_set_cpu(tcon, encoder, mode);
    713		break;
    714	case DRM_MODE_ENCODER_LVDS:
    715		sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
    716		break;
    717	case DRM_MODE_ENCODER_NONE:
    718		sun4i_tcon0_mode_set_rgb(tcon, encoder, mode);
    719		sun4i_tcon_set_mux(tcon, 0, encoder);
    720		break;
    721	case DRM_MODE_ENCODER_TVDAC:
    722	case DRM_MODE_ENCODER_TMDS:
    723		sun4i_tcon1_mode_set(tcon, mode);
    724		sun4i_tcon_set_mux(tcon, 1, encoder);
    725		break;
    726	default:
    727		DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
    728	}
    729}
    730EXPORT_SYMBOL(sun4i_tcon_mode_set);
    731
    732static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
    733					struct sun4i_crtc *scrtc)
    734{
    735	unsigned long flags;
    736
    737	spin_lock_irqsave(&dev->event_lock, flags);
    738	if (scrtc->event) {
    739		drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event);
    740		drm_crtc_vblank_put(&scrtc->crtc);
    741		scrtc->event = NULL;
    742	}
    743	spin_unlock_irqrestore(&dev->event_lock, flags);
    744}
    745
    746static irqreturn_t sun4i_tcon_handler(int irq, void *private)
    747{
    748	struct sun4i_tcon *tcon = private;
    749	struct drm_device *drm = tcon->drm;
    750	struct sun4i_crtc *scrtc = tcon->crtc;
    751	struct sunxi_engine *engine = scrtc->engine;
    752	unsigned int status;
    753
    754	regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
    755
    756	if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) |
    757			SUN4I_TCON_GINT0_VBLANK_INT(1) |
    758			SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT)))
    759		return IRQ_NONE;
    760
    761	drm_crtc_handle_vblank(&scrtc->crtc);
    762	sun4i_tcon_finish_page_flip(drm, scrtc);
    763
    764	/* Acknowledge the interrupt */
    765	regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG,
    766			   SUN4I_TCON_GINT0_VBLANK_INT(0) |
    767			   SUN4I_TCON_GINT0_VBLANK_INT(1) |
    768			   SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT,
    769			   0);
    770
    771	if (engine->ops->vblank_quirk)
    772		engine->ops->vblank_quirk(engine);
    773
    774	return IRQ_HANDLED;
    775}
    776
    777static int sun4i_tcon_init_clocks(struct device *dev,
    778				  struct sun4i_tcon *tcon)
    779{
    780	tcon->clk = devm_clk_get(dev, "ahb");
    781	if (IS_ERR(tcon->clk)) {
    782		dev_err(dev, "Couldn't get the TCON bus clock\n");
    783		return PTR_ERR(tcon->clk);
    784	}
    785	clk_prepare_enable(tcon->clk);
    786
    787	if (tcon->quirks->has_channel_0) {
    788		tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
    789		if (IS_ERR(tcon->sclk0)) {
    790			dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
    791			return PTR_ERR(tcon->sclk0);
    792		}
    793	}
    794	clk_prepare_enable(tcon->sclk0);
    795
    796	if (tcon->quirks->has_channel_1) {
    797		tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
    798		if (IS_ERR(tcon->sclk1)) {
    799			dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
    800			return PTR_ERR(tcon->sclk1);
    801		}
    802	}
    803
    804	return 0;
    805}
    806
    807static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
    808{
    809	clk_disable_unprepare(tcon->sclk0);
    810	clk_disable_unprepare(tcon->clk);
    811}
    812
    813static int sun4i_tcon_init_irq(struct device *dev,
    814			       struct sun4i_tcon *tcon)
    815{
    816	struct platform_device *pdev = to_platform_device(dev);
    817	int irq, ret;
    818
    819	irq = platform_get_irq(pdev, 0);
    820	if (irq < 0)
    821		return irq;
    822
    823	ret = devm_request_irq(dev, irq, sun4i_tcon_handler, 0,
    824			       dev_name(dev), tcon);
    825	if (ret) {
    826		dev_err(dev, "Couldn't request the IRQ\n");
    827		return ret;
    828	}
    829
    830	return 0;
    831}
    832
    833static const struct regmap_config sun4i_tcon_regmap_config = {
    834	.reg_bits	= 32,
    835	.val_bits	= 32,
    836	.reg_stride	= 4,
    837	.max_register	= 0x800,
    838};
    839
    840static int sun4i_tcon_init_regmap(struct device *dev,
    841				  struct sun4i_tcon *tcon)
    842{
    843	struct platform_device *pdev = to_platform_device(dev);
    844	void __iomem *regs;
    845
    846	regs = devm_platform_ioremap_resource(pdev, 0);
    847	if (IS_ERR(regs))
    848		return PTR_ERR(regs);
    849
    850	tcon->regs = devm_regmap_init_mmio(dev, regs,
    851					   &sun4i_tcon_regmap_config);
    852	if (IS_ERR(tcon->regs)) {
    853		dev_err(dev, "Couldn't create the TCON regmap\n");
    854		return PTR_ERR(tcon->regs);
    855	}
    856
    857	/* Make sure the TCON is disabled and all IRQs are off */
    858	regmap_write(tcon->regs, SUN4I_TCON_GCTL_REG, 0);
    859	regmap_write(tcon->regs, SUN4I_TCON_GINT0_REG, 0);
    860	regmap_write(tcon->regs, SUN4I_TCON_GINT1_REG, 0);
    861
    862	/* Disable IO lines and set them to tristate */
    863	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, ~0);
    864	regmap_write(tcon->regs, SUN4I_TCON1_IO_TRI_REG, ~0);
    865
    866	return 0;
    867}
    868
    869/*
    870 * On SoCs with the old display pipeline design (Display Engine 1.0),
    871 * the TCON is always tied to just one backend. Hence we can traverse
    872 * the of_graph upwards to find the backend our tcon is connected to,
    873 * and take its ID as our own.
    874 *
    875 * We can either identify backends from their compatible strings, which
    876 * means maintaining a large list of them. Or, since the backend is
    877 * registered and binded before the TCON, we can just go through the
    878 * list of registered backends and compare the device node.
    879 *
    880 * As the structures now store engines instead of backends, here this
    881 * function in fact searches the corresponding engine, and the ID is
    882 * requested via the get_id function of the engine.
    883 */
    884static struct sunxi_engine *
    885sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
    886				struct device_node *node,
    887				u32 port_id)
    888{
    889	struct device_node *port, *ep, *remote;
    890	struct sunxi_engine *engine = ERR_PTR(-EINVAL);
    891	u32 reg = 0;
    892
    893	port = of_graph_get_port_by_id(node, port_id);
    894	if (!port)
    895		return ERR_PTR(-EINVAL);
    896
    897	/*
    898	 * This only works if there is only one path from the TCON
    899	 * to any display engine. Otherwise the probe order of the
    900	 * TCONs and display engines is not guaranteed. They may
    901	 * either bind to the wrong one, or worse, bind to the same
    902	 * one if additional checks are not done.
    903	 *
    904	 * Bail out if there are multiple input connections.
    905	 */
    906	if (of_get_available_child_count(port) != 1)
    907		goto out_put_port;
    908
    909	/* Get the first connection without specifying an ID */
    910	ep = of_get_next_available_child(port, NULL);
    911	if (!ep)
    912		goto out_put_port;
    913
    914	remote = of_graph_get_remote_port_parent(ep);
    915	if (!remote)
    916		goto out_put_ep;
    917
    918	/* does this node match any registered engines? */
    919	list_for_each_entry(engine, &drv->engine_list, list)
    920		if (remote == engine->node)
    921			goto out_put_remote;
    922
    923	/*
    924	 * According to device tree binding input ports have even id
    925	 * number and output ports have odd id. Since component with
    926	 * more than one input and one output (TCON TOP) exits, correct
    927	 * remote input id has to be calculated by subtracting 1 from
    928	 * remote output id. If this for some reason can't be done, 0
    929	 * is used as input port id.
    930	 */
    931	of_node_put(port);
    932	port = of_graph_get_remote_port(ep);
    933	if (!of_property_read_u32(port, "reg", &reg) && reg > 0)
    934		reg -= 1;
    935
    936	/* keep looking through upstream ports */
    937	engine = sun4i_tcon_find_engine_traverse(drv, remote, reg);
    938
    939out_put_remote:
    940	of_node_put(remote);
    941out_put_ep:
    942	of_node_put(ep);
    943out_put_port:
    944	of_node_put(port);
    945
    946	return engine;
    947}
    948
    949/*
    950 * The device tree binding says that the remote endpoint ID of any
    951 * connection between components, up to and including the TCON, of
    952 * the display pipeline should be equal to the actual ID of the local
    953 * component. Thus we can look at any one of the input connections of
    954 * the TCONs, and use that connection's remote endpoint ID as our own.
    955 *
    956 * Since the user of this function already finds the input port,
    957 * the port is passed in directly without further checks.
    958 */
    959static int sun4i_tcon_of_get_id_from_port(struct device_node *port)
    960{
    961	struct device_node *ep;
    962	int ret = -EINVAL;
    963
    964	/* try finding an upstream endpoint */
    965	for_each_available_child_of_node(port, ep) {
    966		struct device_node *remote;
    967		u32 reg;
    968
    969		remote = of_graph_get_remote_endpoint(ep);
    970		if (!remote)
    971			continue;
    972
    973		ret = of_property_read_u32(remote, "reg", &reg);
    974		if (ret)
    975			continue;
    976
    977		ret = reg;
    978	}
    979
    980	return ret;
    981}
    982
    983/*
    984 * Once we know the TCON's id, we can look through the list of
    985 * engines to find a matching one. We assume all engines have
    986 * been probed and added to the list.
    987 */
    988static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
    989							int id)
    990{
    991	struct sunxi_engine *engine;
    992
    993	list_for_each_entry(engine, &drv->engine_list, list)
    994		if (engine->id == id)
    995			return engine;
    996
    997	return ERR_PTR(-EINVAL);
    998}
    999
   1000static bool sun4i_tcon_connected_to_tcon_top(struct device_node *node)
   1001{
   1002	struct device_node *remote;
   1003	bool ret = false;
   1004
   1005	remote = of_graph_get_remote_node(node, 0, -1);
   1006	if (remote) {
   1007		ret = !!(IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
   1008			 of_match_node(sun8i_tcon_top_of_table, remote));
   1009		of_node_put(remote);
   1010	}
   1011
   1012	return ret;
   1013}
   1014
   1015static int sun4i_tcon_get_index(struct sun4i_drv *drv)
   1016{
   1017	struct list_head *pos;
   1018	int size = 0;
   1019
   1020	/*
   1021	 * Because TCON is added to the list at the end of the probe
   1022	 * (after this function is called), index of the current TCON
   1023	 * will be same as current TCON list size.
   1024	 */
   1025	list_for_each(pos, &drv->tcon_list)
   1026		++size;
   1027
   1028	return size;
   1029}
   1030
   1031/*
   1032 * On SoCs with the old display pipeline design (Display Engine 1.0),
   1033 * we assumed the TCON was always tied to just one backend. However
   1034 * this proved not to be the case. On the A31, the TCON can select
   1035 * either backend as its source. On the A20 (and likely on the A10),
   1036 * the backend can choose which TCON to output to.
   1037 *
   1038 * The device tree binding says that the remote endpoint ID of any
   1039 * connection between components, up to and including the TCON, of
   1040 * the display pipeline should be equal to the actual ID of the local
   1041 * component. Thus we should be able to look at any one of the input
   1042 * connections of the TCONs, and use that connection's remote endpoint
   1043 * ID as our own.
   1044 *
   1045 * However  the connections between the backend and TCON were assumed
   1046 * to be always singular, and their endpoit IDs were all incorrectly
   1047 * set to 0. This means for these old device trees, we cannot just look
   1048 * up the remote endpoint ID of a TCON input endpoint. TCON1 would be
   1049 * incorrectly identified as TCON0.
   1050 *
   1051 * This function first checks if the TCON node has 2 input endpoints.
   1052 * If so, then the device tree is a corrected version, and it will use
   1053 * sun4i_tcon_of_get_id() and sun4i_tcon_get_engine_by_id() from above
   1054 * to fetch the ID and engine directly. If not, then it is likely an
   1055 * old device trees, where the endpoint IDs were incorrect, but did not
   1056 * have endpoint connections between the backend and TCON across
   1057 * different display pipelines. It will fall back to the old method of
   1058 * traversing the  of_graph to try and find a matching engine by device
   1059 * node.
   1060 *
   1061 * In the case of single display pipeline device trees, either method
   1062 * works.
   1063 */
   1064static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
   1065						   struct device_node *node)
   1066{
   1067	struct device_node *port;
   1068	struct sunxi_engine *engine;
   1069
   1070	port = of_graph_get_port_by_id(node, 0);
   1071	if (!port)
   1072		return ERR_PTR(-EINVAL);
   1073
   1074	/*
   1075	 * Is this a corrected device tree with cross pipeline
   1076	 * connections between the backend and TCON?
   1077	 */
   1078	if (of_get_child_count(port) > 1) {
   1079		int id;
   1080
   1081		/*
   1082		 * When pipeline has the same number of TCONs and engines which
   1083		 * are represented by frontends/backends (DE1) or mixers (DE2),
   1084		 * we match them by their respective IDs. However, if pipeline
   1085		 * contains TCON TOP, chances are that there are either more
   1086		 * TCONs than engines (R40) or TCONs with non-consecutive ids.
   1087		 * (H6). In that case it's easier just use TCON index in list
   1088		 * as an id. That means that on R40, any 2 TCONs can be enabled
   1089		 * in DT out of 4 (there are 2 mixers). Due to the design of
   1090		 * TCON TOP, remaining 2 TCONs can't be connected to anything
   1091		 * anyway.
   1092		 */
   1093		if (sun4i_tcon_connected_to_tcon_top(node))
   1094			id = sun4i_tcon_get_index(drv);
   1095		else
   1096			id = sun4i_tcon_of_get_id_from_port(port);
   1097
   1098		/* Get our engine by matching our ID */
   1099		engine = sun4i_tcon_get_engine_by_id(drv, id);
   1100
   1101		of_node_put(port);
   1102		return engine;
   1103	}
   1104
   1105	/* Fallback to old method by traversing input endpoints */
   1106	of_node_put(port);
   1107	return sun4i_tcon_find_engine_traverse(drv, node, 0);
   1108}
   1109
   1110static int sun4i_tcon_bind(struct device *dev, struct device *master,
   1111			   void *data)
   1112{
   1113	struct drm_device *drm = data;
   1114	struct sun4i_drv *drv = drm->dev_private;
   1115	struct sunxi_engine *engine;
   1116	struct device_node *remote;
   1117	struct sun4i_tcon *tcon;
   1118	struct reset_control *edp_rstc;
   1119	bool has_lvds_rst, has_lvds_alt, can_lvds;
   1120	int ret;
   1121
   1122	engine = sun4i_tcon_find_engine(drv, dev->of_node);
   1123	if (IS_ERR(engine)) {
   1124		dev_err(dev, "Couldn't find matching engine\n");
   1125		return -EPROBE_DEFER;
   1126	}
   1127
   1128	tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
   1129	if (!tcon)
   1130		return -ENOMEM;
   1131	dev_set_drvdata(dev, tcon);
   1132	tcon->drm = drm;
   1133	tcon->dev = dev;
   1134	tcon->id = engine->id;
   1135	tcon->quirks = of_device_get_match_data(dev);
   1136
   1137	tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
   1138	if (IS_ERR(tcon->lcd_rst)) {
   1139		dev_err(dev, "Couldn't get our reset line\n");
   1140		return PTR_ERR(tcon->lcd_rst);
   1141	}
   1142
   1143	if (tcon->quirks->needs_edp_reset) {
   1144		edp_rstc = devm_reset_control_get_shared(dev, "edp");
   1145		if (IS_ERR(edp_rstc)) {
   1146			dev_err(dev, "Couldn't get edp reset line\n");
   1147			return PTR_ERR(edp_rstc);
   1148		}
   1149
   1150		ret = reset_control_deassert(edp_rstc);
   1151		if (ret) {
   1152			dev_err(dev, "Couldn't deassert edp reset line\n");
   1153			return ret;
   1154		}
   1155	}
   1156
   1157	/* Make sure our TCON is reset */
   1158	ret = reset_control_reset(tcon->lcd_rst);
   1159	if (ret) {
   1160		dev_err(dev, "Couldn't deassert our reset line\n");
   1161		return ret;
   1162	}
   1163
   1164	if (tcon->quirks->supports_lvds) {
   1165		/*
   1166		 * This can only be made optional since we've had DT
   1167		 * nodes without the LVDS reset properties.
   1168		 *
   1169		 * If the property is missing, just disable LVDS, and
   1170		 * print a warning.
   1171		 */
   1172		tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
   1173		if (IS_ERR(tcon->lvds_rst)) {
   1174			dev_err(dev, "Couldn't get our reset line\n");
   1175			return PTR_ERR(tcon->lvds_rst);
   1176		} else if (tcon->lvds_rst) {
   1177			has_lvds_rst = true;
   1178			reset_control_reset(tcon->lvds_rst);
   1179		} else {
   1180			has_lvds_rst = false;
   1181		}
   1182
   1183		/*
   1184		 * This can only be made optional since we've had DT
   1185		 * nodes without the LVDS reset properties.
   1186		 *
   1187		 * If the property is missing, just disable LVDS, and
   1188		 * print a warning.
   1189		 */
   1190		if (tcon->quirks->has_lvds_alt) {
   1191			tcon->lvds_pll = devm_clk_get(dev, "lvds-alt");
   1192			if (IS_ERR(tcon->lvds_pll)) {
   1193				if (PTR_ERR(tcon->lvds_pll) == -ENOENT) {
   1194					has_lvds_alt = false;
   1195				} else {
   1196					dev_err(dev, "Couldn't get the LVDS PLL\n");
   1197					return PTR_ERR(tcon->lvds_pll);
   1198				}
   1199			} else {
   1200				has_lvds_alt = true;
   1201			}
   1202		}
   1203
   1204		if (!has_lvds_rst ||
   1205		    (tcon->quirks->has_lvds_alt && !has_lvds_alt)) {
   1206			dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n");
   1207			dev_warn(dev, "LVDS output disabled\n");
   1208			can_lvds = false;
   1209		} else {
   1210			can_lvds = true;
   1211		}
   1212	} else {
   1213		can_lvds = false;
   1214	}
   1215
   1216	ret = sun4i_tcon_init_clocks(dev, tcon);
   1217	if (ret) {
   1218		dev_err(dev, "Couldn't init our TCON clocks\n");
   1219		goto err_assert_reset;
   1220	}
   1221
   1222	ret = sun4i_tcon_init_regmap(dev, tcon);
   1223	if (ret) {
   1224		dev_err(dev, "Couldn't init our TCON regmap\n");
   1225		goto err_free_clocks;
   1226	}
   1227
   1228	if (tcon->quirks->has_channel_0) {
   1229		ret = sun4i_dclk_create(dev, tcon);
   1230		if (ret) {
   1231			dev_err(dev, "Couldn't create our TCON dot clock\n");
   1232			goto err_free_clocks;
   1233		}
   1234	}
   1235
   1236	ret = sun4i_tcon_init_irq(dev, tcon);
   1237	if (ret) {
   1238		dev_err(dev, "Couldn't init our TCON interrupts\n");
   1239		goto err_free_dotclock;
   1240	}
   1241
   1242	tcon->crtc = sun4i_crtc_init(drm, engine, tcon);
   1243	if (IS_ERR(tcon->crtc)) {
   1244		dev_err(dev, "Couldn't create our CRTC\n");
   1245		ret = PTR_ERR(tcon->crtc);
   1246		goto err_free_dotclock;
   1247	}
   1248
   1249	if (tcon->quirks->has_channel_0) {
   1250		/*
   1251		 * If we have an LVDS panel connected to the TCON, we should
   1252		 * just probe the LVDS connector. Otherwise, just probe RGB as
   1253		 * we used to.
   1254		 */
   1255		remote = of_graph_get_remote_node(dev->of_node, 1, 0);
   1256		if (of_device_is_compatible(remote, "panel-lvds"))
   1257			if (can_lvds)
   1258				ret = sun4i_lvds_init(drm, tcon);
   1259			else
   1260				ret = -EINVAL;
   1261		else
   1262			ret = sun4i_rgb_init(drm, tcon);
   1263		of_node_put(remote);
   1264
   1265		if (ret < 0)
   1266			goto err_free_dotclock;
   1267	}
   1268
   1269	if (tcon->quirks->needs_de_be_mux) {
   1270		/*
   1271		 * We assume there is no dynamic muxing of backends
   1272		 * and TCONs, so we select the backend with same ID.
   1273		 *
   1274		 * While dynamic selection might be interesting, since
   1275		 * the CRTC is tied to the TCON, while the layers are
   1276		 * tied to the backends, this means, we will need to
   1277		 * switch between groups of layers. There might not be
   1278		 * a way to represent this constraint in DRM.
   1279		 */
   1280		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
   1281				   SUN4I_TCON0_CTL_SRC_SEL_MASK,
   1282				   tcon->id);
   1283		regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
   1284				   SUN4I_TCON1_CTL_SRC_SEL_MASK,
   1285				   tcon->id);
   1286	}
   1287
   1288	list_add_tail(&tcon->list, &drv->tcon_list);
   1289
   1290	return 0;
   1291
   1292err_free_dotclock:
   1293	if (tcon->quirks->has_channel_0)
   1294		sun4i_dclk_free(tcon);
   1295err_free_clocks:
   1296	sun4i_tcon_free_clocks(tcon);
   1297err_assert_reset:
   1298	reset_control_assert(tcon->lcd_rst);
   1299	return ret;
   1300}
   1301
   1302static void sun4i_tcon_unbind(struct device *dev, struct device *master,
   1303			      void *data)
   1304{
   1305	struct sun4i_tcon *tcon = dev_get_drvdata(dev);
   1306
   1307	list_del(&tcon->list);
   1308	if (tcon->quirks->has_channel_0)
   1309		sun4i_dclk_free(tcon);
   1310	sun4i_tcon_free_clocks(tcon);
   1311}
   1312
   1313static const struct component_ops sun4i_tcon_ops = {
   1314	.bind	= sun4i_tcon_bind,
   1315	.unbind	= sun4i_tcon_unbind,
   1316};
   1317
   1318static int sun4i_tcon_probe(struct platform_device *pdev)
   1319{
   1320	struct device_node *node = pdev->dev.of_node;
   1321	const struct sun4i_tcon_quirks *quirks;
   1322	struct drm_bridge *bridge;
   1323	struct drm_panel *panel;
   1324	int ret;
   1325
   1326	quirks = of_device_get_match_data(&pdev->dev);
   1327
   1328	/* panels and bridges are present only on TCONs with channel 0 */
   1329	if (quirks->has_channel_0) {
   1330		ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
   1331		if (ret == -EPROBE_DEFER)
   1332			return ret;
   1333	}
   1334
   1335	return component_add(&pdev->dev, &sun4i_tcon_ops);
   1336}
   1337
   1338static int sun4i_tcon_remove(struct platform_device *pdev)
   1339{
   1340	component_del(&pdev->dev, &sun4i_tcon_ops);
   1341
   1342	return 0;
   1343}
   1344
   1345/* platform specific TCON muxing callbacks */
   1346static int sun4i_a10_tcon_set_mux(struct sun4i_tcon *tcon,
   1347				  const struct drm_encoder *encoder)
   1348{
   1349	struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
   1350	u32 shift;
   1351
   1352	if (!tcon0)
   1353		return -EINVAL;
   1354
   1355	switch (encoder->encoder_type) {
   1356	case DRM_MODE_ENCODER_TMDS:
   1357		/* HDMI */
   1358		shift = 8;
   1359		break;
   1360	default:
   1361		return -EINVAL;
   1362	}
   1363
   1364	regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
   1365			   0x3 << shift, tcon->id << shift);
   1366
   1367	return 0;
   1368}
   1369
   1370static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
   1371				  const struct drm_encoder *encoder)
   1372{
   1373	u32 val;
   1374
   1375	if (encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
   1376		val = 1;
   1377	else
   1378		val = 0;
   1379
   1380	/*
   1381	 * FIXME: Undocumented bits
   1382	 */
   1383	return regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, val);
   1384}
   1385
   1386static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
   1387			      const struct drm_encoder *encoder)
   1388{
   1389	struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
   1390	u32 shift;
   1391
   1392	if (!tcon0)
   1393		return -EINVAL;
   1394
   1395	switch (encoder->encoder_type) {
   1396	case DRM_MODE_ENCODER_TMDS:
   1397		/* HDMI */
   1398		shift = 8;
   1399		break;
   1400	default:
   1401		/* TODO A31 has MIPI DSI but A31s does not */
   1402		return -EINVAL;
   1403	}
   1404
   1405	regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
   1406			   0x3 << shift, tcon->id << shift);
   1407
   1408	return 0;
   1409}
   1410
   1411static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
   1412				     const struct drm_encoder *encoder)
   1413{
   1414	struct device_node *port, *remote;
   1415	struct platform_device *pdev;
   1416	int id, ret;
   1417
   1418	/* find TCON TOP platform device and TCON id */
   1419
   1420	port = of_graph_get_port_by_id(tcon->dev->of_node, 0);
   1421	if (!port)
   1422		return -EINVAL;
   1423
   1424	id = sun4i_tcon_of_get_id_from_port(port);
   1425	of_node_put(port);
   1426
   1427	remote = of_graph_get_remote_node(tcon->dev->of_node, 0, -1);
   1428	if (!remote)
   1429		return -EINVAL;
   1430
   1431	pdev = of_find_device_by_node(remote);
   1432	of_node_put(remote);
   1433	if (!pdev)
   1434		return -EINVAL;
   1435
   1436	if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
   1437	    encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
   1438		ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id);
   1439		if (ret) {
   1440			put_device(&pdev->dev);
   1441			return ret;
   1442		}
   1443	}
   1444
   1445	if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) {
   1446		ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
   1447		if (ret) {
   1448			put_device(&pdev->dev);
   1449			return ret;
   1450		}
   1451	}
   1452
   1453	return 0;
   1454}
   1455
   1456static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
   1457	.has_channel_0		= true,
   1458	.has_channel_1		= true,
   1459	.dclk_min_div		= 4,
   1460	.set_mux		= sun4i_a10_tcon_set_mux,
   1461};
   1462
   1463static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
   1464	.has_channel_0		= true,
   1465	.has_channel_1		= true,
   1466	.dclk_min_div		= 4,
   1467	.set_mux		= sun5i_a13_tcon_set_mux,
   1468};
   1469
   1470static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
   1471	.has_channel_0		= true,
   1472	.has_channel_1		= true,
   1473	.has_lvds_alt		= true,
   1474	.needs_de_be_mux	= true,
   1475	.dclk_min_div		= 1,
   1476	.set_mux		= sun6i_tcon_set_mux,
   1477};
   1478
   1479static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
   1480	.has_channel_0		= true,
   1481	.has_channel_1		= true,
   1482	.needs_de_be_mux	= true,
   1483	.dclk_min_div		= 1,
   1484};
   1485
   1486static const struct sun4i_tcon_quirks sun7i_a20_tcon0_quirks = {
   1487	.supports_lvds		= true,
   1488	.has_channel_0		= true,
   1489	.has_channel_1		= true,
   1490	.dclk_min_div		= 4,
   1491	/* Same display pipeline structure as A10 */
   1492	.set_mux		= sun4i_a10_tcon_set_mux,
   1493	.setup_lvds_phy		= sun4i_tcon_setup_lvds_phy,
   1494};
   1495
   1496static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
   1497	.has_channel_0		= true,
   1498	.has_channel_1		= true,
   1499	.dclk_min_div		= 4,
   1500	/* Same display pipeline structure as A10 */
   1501	.set_mux		= sun4i_a10_tcon_set_mux,
   1502};
   1503
   1504static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
   1505	.has_channel_0		= true,
   1506	.has_lvds_alt		= true,
   1507	.dclk_min_div		= 1,
   1508	.setup_lvds_phy		= sun6i_tcon_setup_lvds_phy,
   1509	.supports_lvds		= true,
   1510};
   1511
   1512static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
   1513	.supports_lvds		= true,
   1514	.has_channel_0		= true,
   1515	.dclk_min_div		= 1,
   1516	.setup_lvds_phy		= sun6i_tcon_setup_lvds_phy,
   1517};
   1518
   1519static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
   1520	.has_channel_1		= true,
   1521};
   1522
   1523static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
   1524	.has_channel_1		= true,
   1525	.polarity_in_ch0	= true,
   1526	.set_mux		= sun8i_r40_tcon_tv_set_mux,
   1527};
   1528
   1529static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
   1530	.has_channel_0		= true,
   1531	.dclk_min_div		= 1,
   1532};
   1533
   1534static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
   1535	.has_channel_0		= true,
   1536	.needs_edp_reset	= true,
   1537	.dclk_min_div		= 1,
   1538};
   1539
   1540static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
   1541	.has_channel_1	= true,
   1542	.needs_edp_reset = true,
   1543};
   1544
   1545static const struct sun4i_tcon_quirks sun20i_d1_lcd_quirks = {
   1546	.has_channel_0		= true,
   1547	.dclk_min_div		= 1,
   1548	.set_mux		= sun8i_r40_tcon_tv_set_mux,
   1549};
   1550
   1551/* sun4i_drv uses this list to check if a device node is a TCON */
   1552const struct of_device_id sun4i_tcon_of_table[] = {
   1553	{ .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks },
   1554	{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
   1555	{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
   1556	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
   1557	{ .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks },
   1558	{ .compatible = "allwinner,sun7i-a20-tcon0", .data = &sun7i_a20_tcon0_quirks },
   1559	{ .compatible = "allwinner,sun7i-a20-tcon1", .data = &sun7i_a20_quirks },
   1560	{ .compatible = "allwinner,sun8i-a23-tcon", .data = &sun8i_a33_quirks },
   1561	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
   1562	{ .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
   1563	{ .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
   1564	{ .compatible = "allwinner,sun8i-r40-tcon-tv", .data = &sun8i_r40_tv_quirks },
   1565	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
   1566	{ .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
   1567	{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
   1568	{ .compatible = "allwinner,sun20i-d1-tcon-lcd", .data = &sun20i_d1_lcd_quirks },
   1569	{ .compatible = "allwinner,sun20i-d1-tcon-tv", .data = &sun8i_r40_tv_quirks },
   1570	{ }
   1571};
   1572MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
   1573EXPORT_SYMBOL(sun4i_tcon_of_table);
   1574
   1575static struct platform_driver sun4i_tcon_platform_driver = {
   1576	.probe		= sun4i_tcon_probe,
   1577	.remove		= sun4i_tcon_remove,
   1578	.driver		= {
   1579		.name		= "sun4i-tcon",
   1580		.of_match_table	= sun4i_tcon_of_table,
   1581	},
   1582};
   1583module_platform_driver(sun4i_tcon_platform_driver);
   1584
   1585MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
   1586MODULE_DESCRIPTION("Allwinner A10 Timing Controller Driver");
   1587MODULE_LICENSE("GPL");