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_wp.c (7921B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * HDMI wrapper
      4 *
      5 * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/
      6 */
      7
      8#define DSS_SUBSYS_NAME "HDMIWP"
      9
     10#include <linux/kernel.h>
     11#include <linux/err.h>
     12#include <linux/io.h>
     13#include <linux/platform_device.h>
     14#include <linux/seq_file.h>
     15
     16#include "omapdss.h"
     17#include "dss.h"
     18#include "hdmi.h"
     19
     20void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s)
     21{
     22#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(wp->base, r))
     23
     24	DUMPREG(HDMI_WP_REVISION);
     25	DUMPREG(HDMI_WP_SYSCONFIG);
     26	DUMPREG(HDMI_WP_IRQSTATUS_RAW);
     27	DUMPREG(HDMI_WP_IRQSTATUS);
     28	DUMPREG(HDMI_WP_IRQENABLE_SET);
     29	DUMPREG(HDMI_WP_IRQENABLE_CLR);
     30	DUMPREG(HDMI_WP_IRQWAKEEN);
     31	DUMPREG(HDMI_WP_PWR_CTRL);
     32	DUMPREG(HDMI_WP_DEBOUNCE);
     33	DUMPREG(HDMI_WP_VIDEO_CFG);
     34	DUMPREG(HDMI_WP_VIDEO_SIZE);
     35	DUMPREG(HDMI_WP_VIDEO_TIMING_H);
     36	DUMPREG(HDMI_WP_VIDEO_TIMING_V);
     37	DUMPREG(HDMI_WP_CLK);
     38	DUMPREG(HDMI_WP_AUDIO_CFG);
     39	DUMPREG(HDMI_WP_AUDIO_CFG2);
     40	DUMPREG(HDMI_WP_AUDIO_CTRL);
     41	DUMPREG(HDMI_WP_AUDIO_DATA);
     42}
     43
     44u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp)
     45{
     46	return hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
     47}
     48
     49void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus)
     50{
     51	hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, irqstatus);
     52	/* flush posted write */
     53	hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
     54}
     55
     56void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask)
     57{
     58	hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_SET, mask);
     59}
     60
     61void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask)
     62{
     63	hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_CLR, mask);
     64}
     65
     66/* PHY_PWR_CMD */
     67int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val)
     68{
     69	/* Return if already the state */
     70	if (REG_GET(wp->base, HDMI_WP_PWR_CTRL, 5, 4) == val)
     71		return 0;
     72
     73	/* Command for power control of HDMI PHY */
     74	REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 7, 6);
     75
     76	/* Status of the power control of HDMI PHY */
     77	if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val)
     78			!= val) {
     79		DSSERR("Failed to set PHY power mode to %d\n", val);
     80		return -ETIMEDOUT;
     81	}
     82
     83	return 0;
     84}
     85
     86/* PLL_PWR_CMD */
     87int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val)
     88{
     89	/* Command for power control of HDMI PLL */
     90	REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2);
     91
     92	/* wait till PHY_PWR_STATUS is set */
     93	if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val)
     94			!= val) {
     95		DSSERR("Failed to set PLL_PWR_STATUS\n");
     96		return -ETIMEDOUT;
     97	}
     98
     99	return 0;
    100}
    101
    102int hdmi_wp_video_start(struct hdmi_wp_data *wp)
    103{
    104	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, true, 31, 31);
    105
    106	return 0;
    107}
    108
    109void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
    110{
    111	int i;
    112
    113	hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE);
    114
    115	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);
    116
    117	for (i = 0; i < 50; ++i) {
    118		u32 v;
    119
    120		msleep(20);
    121
    122		v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW);
    123		if (v & HDMI_IRQ_VIDEO_FRAME_DONE)
    124			return;
    125	}
    126
    127	DSSERR("no HDMI FRAMEDONE when disabling output\n");
    128}
    129
    130void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
    131		const struct hdmi_video_format *video_fmt)
    132{
    133	u32 l = 0;
    134
    135	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, video_fmt->packing_mode,
    136		10, 8);
    137
    138	l |= FLD_VAL(video_fmt->y_res, 31, 16);
    139	l |= FLD_VAL(video_fmt->x_res, 15, 0);
    140	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_SIZE, l);
    141}
    142
    143void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
    144				    const struct videomode *vm)
    145{
    146	u32 r;
    147	bool vsync_inv, hsync_inv;
    148	DSSDBG("Enter hdmi_wp_video_config_interface\n");
    149
    150	vsync_inv = !!(vm->flags & DISPLAY_FLAGS_VSYNC_LOW);
    151	hsync_inv = !!(vm->flags & DISPLAY_FLAGS_HSYNC_LOW);
    152
    153	r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG);
    154	r = FLD_MOD(r, 1, 7, 7);	/* VSYNC_POL to dispc active high */
    155	r = FLD_MOD(r, 1, 6, 6);	/* HSYNC_POL to dispc active high */
    156	r = FLD_MOD(r, vsync_inv, 5, 5);	/* CORE_VSYNC_INV */
    157	r = FLD_MOD(r, hsync_inv, 4, 4);	/* CORE_HSYNC_INV */
    158	r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 3, 3);
    159	r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
    160	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r);
    161}
    162
    163void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
    164				 const struct videomode *vm)
    165{
    166	u32 timing_h = 0;
    167	u32 timing_v = 0;
    168	unsigned int hsync_len_offset = 1;
    169
    170	DSSDBG("Enter hdmi_wp_video_config_timing\n");
    171
    172	/*
    173	 * On OMAP4 and OMAP5 ES1 the HSW field is programmed as is. On OMAP5
    174	 * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsync_len-1.
    175	 * However, we don't support OMAP5 ES1 at all, so we can just check for
    176	 * OMAP4 here.
    177	 */
    178	if (wp->version == 4)
    179		hsync_len_offset = 0;
    180
    181	timing_h |= FLD_VAL(vm->hback_porch, 31, 20);
    182	timing_h |= FLD_VAL(vm->hfront_porch, 19, 8);
    183	timing_h |= FLD_VAL(vm->hsync_len - hsync_len_offset, 7, 0);
    184	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h);
    185
    186	timing_v |= FLD_VAL(vm->vback_porch, 31, 20);
    187	timing_v |= FLD_VAL(vm->vfront_porch, 19, 8);
    188	timing_v |= FLD_VAL(vm->vsync_len, 7, 0);
    189	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v);
    190}
    191
    192void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
    193		struct videomode *vm, const struct hdmi_config *param)
    194{
    195	DSSDBG("Enter hdmi_wp_video_init_format\n");
    196
    197	video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
    198	video_fmt->y_res = param->vm.vactive;
    199	video_fmt->x_res = param->vm.hactive;
    200
    201	vm->hback_porch = param->vm.hback_porch;
    202	vm->hfront_porch = param->vm.hfront_porch;
    203	vm->hsync_len = param->vm.hsync_len;
    204	vm->vback_porch = param->vm.vback_porch;
    205	vm->vfront_porch = param->vm.vfront_porch;
    206	vm->vsync_len = param->vm.vsync_len;
    207
    208	vm->flags = param->vm.flags;
    209
    210	if (param->vm.flags & DISPLAY_FLAGS_INTERLACED) {
    211		video_fmt->y_res /= 2;
    212		vm->vback_porch /= 2;
    213		vm->vfront_porch /= 2;
    214		vm->vsync_len /= 2;
    215	}
    216
    217	if (param->vm.flags & DISPLAY_FLAGS_DOUBLECLK) {
    218		video_fmt->x_res *= 2;
    219		vm->hfront_porch *= 2;
    220		vm->hsync_len *= 2;
    221		vm->hback_porch *= 2;
    222	}
    223}
    224
    225void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
    226		struct hdmi_audio_format *aud_fmt)
    227{
    228	u32 r;
    229
    230	DSSDBG("Enter hdmi_wp_audio_config_format\n");
    231
    232	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
    233	if (wp->version == 4) {
    234		r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
    235		r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
    236	}
    237	r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
    238	r = FLD_MOD(r, aud_fmt->type, 4, 4);
    239	r = FLD_MOD(r, aud_fmt->justification, 3, 3);
    240	r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
    241	r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
    242	r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
    243	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG, r);
    244}
    245
    246void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
    247		struct hdmi_audio_dma *aud_dma)
    248{
    249	u32 r;
    250
    251	DSSDBG("Enter hdmi_wp_audio_config_dma\n");
    252
    253	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG2);
    254	r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
    255	r = FLD_MOD(r, aud_dma->block_size, 7, 0);
    256	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG2, r);
    257
    258	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CTRL);
    259	r = FLD_MOD(r, aud_dma->mode, 9, 9);
    260	r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
    261	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CTRL, r);
    262}
    263
    264int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable)
    265{
    266	REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 31, 31);
    267
    268	return 0;
    269}
    270
    271int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
    272{
    273	REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 30, 30);
    274
    275	return 0;
    276}
    277
    278int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp,
    279		 unsigned int version)
    280{
    281	struct resource *res;
    282
    283	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp");
    284	wp->base = devm_ioremap_resource(&pdev->dev, res);
    285	if (IS_ERR(wp->base))
    286		return PTR_ERR(wp->base);
    287
    288	wp->phys_base = res->start;
    289	wp->version = version;
    290
    291	return 0;
    292}
    293
    294phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp)
    295{
    296	return wp->phys_base + HDMI_WP_AUDIO_DATA;
    297}