brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · d25ecd4 Raw
214 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) STMicroelectronics SA 20144 * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.5 */6 7#include <drm/drm_print.h>8 9#include "sti_hdmi_tx3g4c28phy.h"10 11#define HDMI_SRZ_CFG                             0x50412#define HDMI_SRZ_PLL_CFG                         0x51013#define HDMI_SRZ_ICNTL                           0x51814#define HDMI_SRZ_CALCODE_EXT                     0x52015 16#define HDMI_SRZ_CFG_EN                          BIT(0)17#define HDMI_SRZ_CFG_DISABLE_BYPASS_SINK_CURRENT BIT(1)18#define HDMI_SRZ_CFG_EXTERNAL_DATA               BIT(16)19#define HDMI_SRZ_CFG_RBIAS_EXT                   BIT(17)20#define HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION      BIT(18)21#define HDMI_SRZ_CFG_EN_BIASRES_DETECTION        BIT(19)22#define HDMI_SRZ_CFG_EN_SRC_TERMINATION          BIT(24)23 24#define HDMI_SRZ_CFG_INTERNAL_MASK  (HDMI_SRZ_CFG_EN     | \25		HDMI_SRZ_CFG_DISABLE_BYPASS_SINK_CURRENT | \26		HDMI_SRZ_CFG_EXTERNAL_DATA               | \27		HDMI_SRZ_CFG_RBIAS_EXT                   | \28		HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION      | \29		HDMI_SRZ_CFG_EN_BIASRES_DETECTION        | \30		HDMI_SRZ_CFG_EN_SRC_TERMINATION)31 32#define PLL_CFG_EN                               BIT(0)33#define PLL_CFG_NDIV_SHIFT                       (8)34#define PLL_CFG_IDF_SHIFT                        (16)35#define PLL_CFG_ODF_SHIFT                        (24)36 37#define ODF_DIV_1                                (0)38#define ODF_DIV_2                                (1)39#define ODF_DIV_4                                (2)40#define ODF_DIV_8                                (3)41 42#define HDMI_TIMEOUT_PLL_LOCK  50  /*milliseconds */43 44struct plldividers_s {45	uint32_t min;46	uint32_t max;47	uint32_t idf;48	uint32_t odf;49};50 51/*52 * Functional specification recommended values53 */54#define NB_PLL_MODE 555static struct plldividers_s plldividers[NB_PLL_MODE] = {56	{0, 20000000, 1, ODF_DIV_8},57	{20000000, 42500000, 2, ODF_DIV_8},58	{42500000, 85000000, 4, ODF_DIV_4},59	{85000000, 170000000, 8, ODF_DIV_2},60	{170000000, 340000000, 16, ODF_DIV_1}61};62 63#define NB_HDMI_PHY_CONFIG 264static struct hdmi_phy_config hdmiphy_config[NB_HDMI_PHY_CONFIG] = {65	{0, 250000000, {0x0, 0x0, 0x0, 0x0} },66	{250000000, 300000000, {0x1110, 0x0, 0x0, 0x0} },67};68 69/**70 * sti_hdmi_tx3g4c28phy_start - Start hdmi phy macro cell tx3g4c2871 *72 * @hdmi: pointer on the hdmi internal structure73 *74 * Return false if an error occur75 */76static bool sti_hdmi_tx3g4c28phy_start(struct sti_hdmi *hdmi)77{78	u32 ckpxpll = hdmi->mode.clock * 1000;79	u32 val, tmdsck, idf, odf, pllctrl = 0;80	bool foundplldivides = false;81	int i;82 83	DRM_DEBUG_DRIVER("ckpxpll = %dHz\n", ckpxpll);84 85	for (i = 0; i < NB_PLL_MODE; i++) {86		if (ckpxpll >= plldividers[i].min &&87		    ckpxpll < plldividers[i].max) {88			idf = plldividers[i].idf;89			odf = plldividers[i].odf;90			foundplldivides = true;91			break;92		}93	}94 95	if (!foundplldivides) {96		DRM_ERROR("input TMDS clock speed (%d) not supported\n",97			  ckpxpll);98		goto err;99	}100 101	/* Assuming no pixel repetition and 24bits color */102	tmdsck = ckpxpll;103	pllctrl |= 40 << PLL_CFG_NDIV_SHIFT;104 105	if (tmdsck > 340000000) {106		DRM_ERROR("output TMDS clock (%d) out of range\n", tmdsck);107		goto err;108	}109 110	pllctrl |= idf << PLL_CFG_IDF_SHIFT;111	pllctrl |= odf << PLL_CFG_ODF_SHIFT;112 113	/*114	 * Configure and power up the PHY PLL115	 */116	hdmi->event_received = false;117	DRM_DEBUG_DRIVER("pllctrl = 0x%x\n", pllctrl);118	hdmi_write(hdmi, (pllctrl | PLL_CFG_EN), HDMI_SRZ_PLL_CFG);119 120	/* wait PLL interrupt */121	wait_event_interruptible_timeout(hdmi->wait_event,122					 hdmi->event_received == true,123					 msecs_to_jiffies124					 (HDMI_TIMEOUT_PLL_LOCK));125 126	if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) == 0) {127		DRM_ERROR("hdmi phy pll not locked\n");128		goto err;129	}130 131	DRM_DEBUG_DRIVER("got PHY PLL Lock\n");132 133	val = (HDMI_SRZ_CFG_EN |134	       HDMI_SRZ_CFG_EXTERNAL_DATA |135	       HDMI_SRZ_CFG_EN_BIASRES_DETECTION |136	       HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION);137 138	if (tmdsck > 165000000)139		val |= HDMI_SRZ_CFG_EN_SRC_TERMINATION;140 141	/*142	 * To configure the source termination and pre-emphasis appropriately143	 * for different high speed TMDS clock frequencies a phy configuration144	 * table must be provided, tailored to the SoC and board combination.145	 */146	for (i = 0; i < NB_HDMI_PHY_CONFIG; i++) {147		if ((hdmiphy_config[i].min_tmds_freq <= tmdsck) &&148		    (hdmiphy_config[i].max_tmds_freq >= tmdsck)) {149			val |= (hdmiphy_config[i].config[0]150				& ~HDMI_SRZ_CFG_INTERNAL_MASK);151			hdmi_write(hdmi, val, HDMI_SRZ_CFG);152 153			val = hdmiphy_config[i].config[1];154			hdmi_write(hdmi, val, HDMI_SRZ_ICNTL);155 156			val = hdmiphy_config[i].config[2];157			hdmi_write(hdmi, val, HDMI_SRZ_CALCODE_EXT);158 159			DRM_DEBUG_DRIVER("serializer cfg 0x%x 0x%x 0x%x\n",160					 hdmiphy_config[i].config[0],161					 hdmiphy_config[i].config[1],162					 hdmiphy_config[i].config[2]);163			return true;164		}165	}166 167	/*168	 * Default, power up the serializer with no pre-emphasis or169	 * output swing correction170	 */171	hdmi_write(hdmi, val,  HDMI_SRZ_CFG);172	hdmi_write(hdmi, 0x0, HDMI_SRZ_ICNTL);173	hdmi_write(hdmi, 0x0, HDMI_SRZ_CALCODE_EXT);174 175	return true;176 177err:178	return false;179}180 181/**182 * sti_hdmi_tx3g4c28phy_stop - Stop hdmi phy macro cell tx3g4c28183 *184 * @hdmi: pointer on the hdmi internal structure185 */186static void sti_hdmi_tx3g4c28phy_stop(struct sti_hdmi *hdmi)187{188	int val = 0;189 190	DRM_DEBUG_DRIVER("\n");191 192	hdmi->event_received = false;193 194	val = HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION;195	val |= HDMI_SRZ_CFG_EN_BIASRES_DETECTION;196 197	hdmi_write(hdmi, val, HDMI_SRZ_CFG);198	hdmi_write(hdmi, 0, HDMI_SRZ_PLL_CFG);199 200	/* wait PLL interrupt */201	wait_event_interruptible_timeout(hdmi->wait_event,202					 hdmi->event_received == true,203					 msecs_to_jiffies204					 (HDMI_TIMEOUT_PLL_LOCK));205 206	if (hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK)207		DRM_ERROR("hdmi phy pll not well disabled\n");208}209 210struct hdmi_phy_ops tx3g4c28phy_ops = {211	.start = sti_hdmi_tx3g4c28phy_start,212	.stop = sti_hdmi_tx3g4c28phy_stop,213};214