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

hdmi_phy.c (4019B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * HDMI PHY
      4 *
      5 * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/err.h>
     10#include <linux/io.h>
     11#include <linux/platform_device.h>
     12#include <linux/slab.h>
     13#include <linux/seq_file.h>
     14
     15#include "omapdss.h"
     16#include "dss.h"
     17#include "hdmi.h"
     18
     19void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
     20{
     21#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
     22		hdmi_read_reg(phy->base, r))
     23
     24	DUMPPHY(HDMI_TXPHY_TX_CTRL);
     25	DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
     26	DUMPPHY(HDMI_TXPHY_POWER_CTRL);
     27	DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
     28	if (phy->features->bist_ctrl)
     29		DUMPPHY(HDMI_TXPHY_BIST_CONTROL);
     30}
     31
     32int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes)
     33{
     34	int i;
     35
     36	for (i = 0; i < 8; i += 2) {
     37		u8 lane, pol;
     38		int dx, dy;
     39
     40		dx = lanes[i];
     41		dy = lanes[i + 1];
     42
     43		if (dx < 0 || dx >= 8)
     44			return -EINVAL;
     45
     46		if (dy < 0 || dy >= 8)
     47			return -EINVAL;
     48
     49		if (dx & 1) {
     50			if (dy != dx - 1)
     51				return -EINVAL;
     52			pol = 1;
     53		} else {
     54			if (dy != dx + 1)
     55				return -EINVAL;
     56			pol = 0;
     57		}
     58
     59		lane = dx / 2;
     60
     61		phy->lane_function[lane] = i / 2;
     62		phy->lane_polarity[lane] = pol;
     63	}
     64
     65	return 0;
     66}
     67
     68static void hdmi_phy_configure_lanes(struct hdmi_phy_data *phy)
     69{
     70	static const u16 pad_cfg_list[] = {
     71		0x0123,
     72		0x0132,
     73		0x0312,
     74		0x0321,
     75		0x0231,
     76		0x0213,
     77		0x1023,
     78		0x1032,
     79		0x3012,
     80		0x3021,
     81		0x2031,
     82		0x2013,
     83		0x1203,
     84		0x1302,
     85		0x3102,
     86		0x3201,
     87		0x2301,
     88		0x2103,
     89		0x1230,
     90		0x1320,
     91		0x3120,
     92		0x3210,
     93		0x2310,
     94		0x2130,
     95	};
     96
     97	u16 lane_cfg = 0;
     98	int i;
     99	unsigned int lane_cfg_val;
    100	u16 pol_val = 0;
    101
    102	for (i = 0; i < 4; ++i)
    103		lane_cfg |= phy->lane_function[i] << ((3 - i) * 4);
    104
    105	pol_val |= phy->lane_polarity[0] << 0;
    106	pol_val |= phy->lane_polarity[1] << 3;
    107	pol_val |= phy->lane_polarity[2] << 2;
    108	pol_val |= phy->lane_polarity[3] << 1;
    109
    110	for (i = 0; i < ARRAY_SIZE(pad_cfg_list); ++i)
    111		if (pad_cfg_list[i] == lane_cfg)
    112			break;
    113
    114	if (WARN_ON(i == ARRAY_SIZE(pad_cfg_list)))
    115		i = 0;
    116
    117	lane_cfg_val = i;
    118
    119	REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, lane_cfg_val, 26, 22);
    120	REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27);
    121}
    122
    123int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
    124	unsigned long lfbitclk)
    125{
    126	u8 freqout;
    127
    128	/*
    129	 * Read address 0 in order to get the SCP reset done completed
    130	 * Dummy access performed to make sure reset is done
    131	 */
    132	hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL);
    133
    134	/*
    135	 * In OMAP5+, the HFBITCLK must be divided by 2 before issuing the
    136	 * HDMI_PHYPWRCMD_LDOON command.
    137	*/
    138	if (phy->features->bist_ctrl)
    139		REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11);
    140
    141	/*
    142	 * If the hfbitclk != lfbitclk, it means the lfbitclk was configured
    143	 * to be used for TMDS.
    144	 */
    145	if (hfbitclk != lfbitclk)
    146		freqout = 0;
    147	else if (hfbitclk / 10 < phy->features->max_phy)
    148		freqout = 1;
    149	else
    150		freqout = 2;
    151
    152	/*
    153	 * Write to phy address 0 to configure the clock
    154	 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
    155	 */
    156	REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, freqout, 31, 30);
    157
    158	/* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
    159	hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
    160
    161	/* Setup max LDO voltage */
    162	if (phy->features->ldo_voltage)
    163		REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
    164
    165	hdmi_phy_configure_lanes(phy);
    166
    167	return 0;
    168}
    169
    170static const struct hdmi_phy_features omap44xx_phy_feats = {
    171	.bist_ctrl	=	false,
    172	.ldo_voltage	=	true,
    173	.max_phy	=	185675000,
    174};
    175
    176static const struct hdmi_phy_features omap54xx_phy_feats = {
    177	.bist_ctrl	=	true,
    178	.ldo_voltage	=	false,
    179	.max_phy	=	186000000,
    180};
    181
    182int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy,
    183		  unsigned int version)
    184{
    185	if (version == 4)
    186		phy->features = &omap44xx_phy_feats;
    187	else
    188		phy->features = &omap54xx_phy_feats;
    189
    190	phy->base = devm_platform_ioremap_resource_byname(pdev, "phy");
    191	if (IS_ERR(phy->base))
    192		return PTR_ERR(phy->base);
    193
    194	return 0;
    195}