brintos

brintos / linux-shallow public Read only

0
0
Text · 7.3 KiB · 41ad52b Raw
282 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * HDMI wrapper4 *5 * Copyright (C) 2013 Texas Instruments Incorporated6 */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 <video/omapfb_dss.h>17 18#include "dss.h"19#include "hdmi.h"20 21void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s)22{23#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(wp->base, r))24 25	DUMPREG(HDMI_WP_REVISION);26	DUMPREG(HDMI_WP_SYSCONFIG);27	DUMPREG(HDMI_WP_IRQSTATUS_RAW);28	DUMPREG(HDMI_WP_IRQSTATUS);29	DUMPREG(HDMI_WP_IRQENABLE_SET);30	DUMPREG(HDMI_WP_IRQENABLE_CLR);31	DUMPREG(HDMI_WP_IRQWAKEEN);32	DUMPREG(HDMI_WP_PWR_CTRL);33	DUMPREG(HDMI_WP_DEBOUNCE);34	DUMPREG(HDMI_WP_VIDEO_CFG);35	DUMPREG(HDMI_WP_VIDEO_SIZE);36	DUMPREG(HDMI_WP_VIDEO_TIMING_H);37	DUMPREG(HDMI_WP_VIDEO_TIMING_V);38	DUMPREG(HDMI_WP_CLK);39	DUMPREG(HDMI_WP_AUDIO_CFG);40	DUMPREG(HDMI_WP_AUDIO_CFG2);41	DUMPREG(HDMI_WP_AUDIO_CTRL);42	DUMPREG(HDMI_WP_AUDIO_DATA);43}44 45u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp)46{47	return hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);48}49 50void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus)51{52	hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, irqstatus);53	/* flush posted write */54	hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);55}56 57void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask)58{59	hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_SET, mask);60}61 62void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask)63{64	hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_CLR, mask);65}66 67/* PHY_PWR_CMD */68int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val)69{70	/* Return if already the state */71	if (REG_GET(wp->base, HDMI_WP_PWR_CTRL, 5, 4) == val)72		return 0;73 74	/* Command for power control of HDMI PHY */75	REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 7, 6);76 77	/* Status of the power control of HDMI PHY */78	if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val)79			!= val) {80		DSSERR("Failed to set PHY power mode to %d\n", val);81		return -ETIMEDOUT;82	}83 84	return 0;85}86 87/* PLL_PWR_CMD */88int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val)89{90	/* Command for power control of HDMI PLL */91	REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2);92 93	/* wait till PHY_PWR_STATUS is set */94	if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val)95			!= val) {96		DSSERR("Failed to set PLL_PWR_STATUS\n");97		return -ETIMEDOUT;98	}99 100	return 0;101}102 103int hdmi_wp_video_start(struct hdmi_wp_data *wp)104{105	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, true, 31, 31);106 107	return 0;108}109 110void hdmi_wp_video_stop(struct hdmi_wp_data *wp)111{112	int i;113 114	hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE);115 116	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);117 118	for (i = 0; i < 50; ++i) {119		u32 v;120 121		msleep(20);122 123		v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW);124		if (v & HDMI_IRQ_VIDEO_FRAME_DONE)125			return;126	}127 128	DSSERR("no HDMI FRAMEDONE when disabling output\n");129}130 131void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,132		struct hdmi_video_format *video_fmt)133{134	u32 l = 0;135 136	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, video_fmt->packing_mode,137		10, 8);138 139	l |= FLD_VAL(video_fmt->y_res, 31, 16);140	l |= FLD_VAL(video_fmt->x_res, 15, 0);141	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_SIZE, l);142}143 144void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,145		struct omap_video_timings *timings)146{147	u32 r;148	bool vsync_pol, hsync_pol;149	DSSDBG("Enter hdmi_wp_video_config_interface\n");150 151	vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;152	hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;153 154	r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG);155	r = FLD_MOD(r, vsync_pol, 7, 7);156	r = FLD_MOD(r, hsync_pol, 6, 6);157	r = FLD_MOD(r, timings->interlace, 3, 3);158	r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */159	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r);160}161 162void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,163		struct omap_video_timings *timings)164{165	u32 timing_h = 0;166	u32 timing_v = 0;167 168	DSSDBG("Enter hdmi_wp_video_config_timing\n");169 170	timing_h |= FLD_VAL(timings->hbp, 31, 20);171	timing_h |= FLD_VAL(timings->hfp, 19, 8);172	timing_h |= FLD_VAL(timings->hsw, 7, 0);173	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h);174 175	timing_v |= FLD_VAL(timings->vbp, 31, 20);176	timing_v |= FLD_VAL(timings->vfp, 19, 8);177	timing_v |= FLD_VAL(timings->vsw, 7, 0);178	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v);179}180 181void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,182		struct omap_video_timings *timings, struct hdmi_config *param)183{184	DSSDBG("Enter hdmi_wp_video_init_format\n");185 186	video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;187	video_fmt->y_res = param->timings.y_res;188	video_fmt->x_res = param->timings.x_res;189	if (param->timings.interlace)190		video_fmt->y_res /= 2;191 192	timings->hbp = param->timings.hbp;193	timings->hfp = param->timings.hfp;194	timings->hsw = param->timings.hsw;195	timings->vbp = param->timings.vbp;196	timings->vfp = param->timings.vfp;197	timings->vsw = param->timings.vsw;198	timings->vsync_level = param->timings.vsync_level;199	timings->hsync_level = param->timings.hsync_level;200	timings->interlace = param->timings.interlace;201}202 203void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,204		struct hdmi_audio_format *aud_fmt)205{206	u32 r;207 208	DSSDBG("Enter hdmi_wp_audio_config_format\n");209 210	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);211	if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 ||212	    omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||213	    omapdss_get_version() == OMAPDSS_VER_OMAP4) {214		r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);215		r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);216	}217	r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);218	r = FLD_MOD(r, aud_fmt->type, 4, 4);219	r = FLD_MOD(r, aud_fmt->justification, 3, 3);220	r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);221	r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);222	r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);223	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG, r);224}225 226void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,227		struct hdmi_audio_dma *aud_dma)228{229	u32 r;230 231	DSSDBG("Enter hdmi_wp_audio_config_dma\n");232 233	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG2);234	r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);235	r = FLD_MOD(r, aud_dma->block_size, 7, 0);236	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG2, r);237 238	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CTRL);239	r = FLD_MOD(r, aud_dma->mode, 9, 9);240	r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);241	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CTRL, r);242}243 244int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable)245{246	REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 31, 31);247 248	return 0;249}250 251int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)252{253	REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 30, 30);254 255	return 0;256}257 258int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)259{260	struct resource *res;261 262	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp");263	if (!res) {264		DSSERR("can't get WP mem resource\n");265		return -EINVAL;266	}267	wp->phys_base = res->start;268 269	wp->base = devm_ioremap_resource(&pdev->dev, res);270	if (IS_ERR(wp->base)) {271		DSSERR("can't ioremap HDMI WP\n");272		return PTR_ERR(wp->base);273	}274 275	return 0;276}277 278phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp)279{280	return wp->phys_base + HDMI_WP_AUDIO_DATA;281}282