diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2017-02-26 04:44:59 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-26 04:44:59 -0800 |
| commit | 49d57d9b26e1a73dfe6e6ec5dfc3725908483696 (patch) | |
| tree | 138796f74efb4b075bbc65a64f9a8e204e26cd7c /drivers/gpu | |
| parent | 690cee7544570f71f5b9fe368f09ec941fa06916 (diff) | |
| parent | 51766baf781deb6b2e3b31b78434bdfff70a50cd (diff) | |
Merge "drm/msm: add hdmi audio support for sde kms"
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/msm/Makefile | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c | 34 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h | 44 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_audio.c | 393 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c | 388 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_regs.h | 300 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi.xml.h | 3 |
7 files changed, 1161 insertions, 5 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 4e968cf24479..d81ec8918ce7 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -98,7 +98,9 @@ msm_drm-$(CONFIG_DRM_MSM_DSI_STAGING) += dsi-staging/dsi_phy.o \ dsi-staging/dsi_display_test.o msm_drm-$(CONFIG_DRM_SDE_HDMI) += \ - hdmi-staging/sde_hdmi.o + hdmi-staging/sde_hdmi.o \ + hdmi-staging/sde_hdmi_bridge.o \ + hdmi-staging/sde_hdmi_audio.o msm_drm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/pll/dsi_pll.o \ dsi/pll/dsi_pll_28nm.o diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index 6a020b3d8886..15e2d69827e7 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -325,9 +325,9 @@ static int _sde_hdmi_hpd_enable(struct sde_hdmi *sde_hdmi) } } - hdmi_set_mode(hdmi, false); + sde_hdmi_set_mode(hdmi, false); _sde_hdmi_phy_reset(hdmi); - hdmi_set_mode(hdmi, true); + sde_hdmi_set_mode(hdmi, true); hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b); @@ -367,7 +367,7 @@ static void _sde_hdmi_hdp_disable(struct sde_hdmi *sde_hdmi) /* Disable HPD interrupt */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0); - hdmi_set_mode(hdmi, false); + sde_hdmi_set_mode(hdmi, false); for (i = 0; i < config->hpd_clk_cnt; i++) clk_disable_unprepare(hdmi->hpd_clks[i]); @@ -460,6 +460,32 @@ static irqreturn_t _sde_hdmi_irq(int irq, void *dev_id) return IRQ_HANDLED; } +void sde_hdmi_set_mode(struct hdmi *hdmi, bool power_on) +{ + uint32_t ctrl = 0; + unsigned long flags; + + spin_lock_irqsave(&hdmi->reg_lock, flags); + ctrl = hdmi_read(hdmi, REG_HDMI_CTRL); + if (power_on) { + ctrl |= HDMI_CTRL_ENABLE; + if (!hdmi->hdmi_mode) { + ctrl |= HDMI_CTRL_HDMI; + hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); + ctrl &= ~HDMI_CTRL_HDMI; + } else { + ctrl |= HDMI_CTRL_HDMI; + } + } else { + ctrl &= ~HDMI_CTRL_HDMI; + } + + hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); + spin_unlock_irqrestore(&hdmi->reg_lock, flags); + DRM_DEBUG("HDMI Core: %s, HDMI_CTRL=0x%08x\n", + power_on ? "Enable" : "Disable", ctrl); +} + int sde_hdmi_get_info(struct msm_display_info *info, void *display) { @@ -1087,7 +1113,7 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc) hdmi_audio_infoframe_init(&hdmi->audio.infoframe); - hdmi->bridge = hdmi_bridge_init(hdmi); + hdmi->bridge = sde_hdmi_bridge_init(hdmi); if (IS_ERR(hdmi->bridge)) { rc = PTR_ERR(hdmi->bridge); SDE_ERROR("failed to create HDMI bridge: %d\n", rc); diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h index ce3937feee9b..1c13d9f875f2 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h @@ -19,6 +19,7 @@ #include <linux/bitops.h> #include <linux/debugfs.h> #include <linux/of_device.h> +#include <linux/msm_ext_display.h> #include <drm/drmP.h> #include <drm/drm_crtc.h> @@ -224,6 +225,49 @@ int sde_hdmi_drm_deinit(struct sde_hdmi *display); int sde_hdmi_get_info(struct msm_display_info *info, void *display); +/** + * sde_hdmi_bridge_init() - init sde hdmi bridge + * @hdmi: Handle to the hdmi. + * + * Return: struct drm_bridge *. + */ +struct drm_bridge *sde_hdmi_bridge_init(struct hdmi *hdmi); + +/** + * sde_hdmi_set_mode() - Set HDMI mode API. + * @hdmi: Handle to the hdmi. + * @power_on: Power on/off request. + * + * Return: void. + */ +void sde_hdmi_set_mode(struct hdmi *hdmi, bool power_on); + +/** + * sde_hdmi_audio_on() - enable hdmi audio. + * @hdmi: Handle to the hdmi. + * @params: audio setup parameters from codec. + * + * Return: error code. + */ +int sde_hdmi_audio_on(struct hdmi *hdmi, + struct msm_ext_disp_audio_setup_params *params); + +/** + * sde_hdmi_audio_off() - disable hdmi audio. + * @hdmi: Handle to the hdmi. + * + * Return: void. + */ +void sde_hdmi_audio_off(struct hdmi *hdmi); + +/** + * sde_hdmi_config_avmute() - mute hdmi. + * @hdmi: Handle to the hdmi. + * @set: enable/disable avmute. + * + * Return: error code. + */ +int sde_hdmi_config_avmute(struct hdmi *hdmi, bool set); #else /*#ifdef CONFIG_DRM_SDE_HDMI*/ static inline u32 sde_hdmi_get_num_of_displays(void) diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_audio.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_audio.c new file mode 100644 index 000000000000..13ea49cfa42d --- /dev/null +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_audio.c @@ -0,0 +1,393 @@ +/* Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/slab.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/iopoll.h> +#include <linux/types.h> +#include <linux/switch.h> +#include <linux/gcd.h> + +#include "drm_edid.h" +#include "sde_kms.h" +#include "sde_hdmi.h" +#include "sde_hdmi_regs.h" +#include "hdmi.h" + +#define HDMI_AUDIO_INFO_FRAME_PACKET_HEADER 0x84 +#define HDMI_AUDIO_INFO_FRAME_PACKET_VERSION 0x1 +#define HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH 0x0A + +#define HDMI_KHZ_TO_HZ 1000 +#define HDMI_MHZ_TO_HZ 1000000 +#define HDMI_ACR_N_MULTIPLIER 128 +#define DEFAULT_AUDIO_SAMPLE_RATE_HZ 48000 + +/* Supported HDMI Audio channels */ +enum hdmi_audio_channels { + AUDIO_CHANNEL_2 = 2, + AUDIO_CHANNEL_3, + AUDIO_CHANNEL_4, + AUDIO_CHANNEL_5, + AUDIO_CHANNEL_6, + AUDIO_CHANNEL_7, + AUDIO_CHANNEL_8, +}; + +/* parameters for clock regeneration */ +struct hdmi_audio_acr { + u32 n; + u32 cts; +}; + +enum hdmi_audio_sample_rates { + AUDIO_SAMPLE_RATE_32KHZ, + AUDIO_SAMPLE_RATE_44_1KHZ, + AUDIO_SAMPLE_RATE_48KHZ, + AUDIO_SAMPLE_RATE_88_2KHZ, + AUDIO_SAMPLE_RATE_96KHZ, + AUDIO_SAMPLE_RATE_176_4KHZ, + AUDIO_SAMPLE_RATE_192KHZ, + AUDIO_SAMPLE_RATE_MAX +}; + +struct sde_hdmi_audio { + struct hdmi *hdmi; + struct msm_ext_disp_audio_setup_params params; + u32 pclk; +}; + +static void _sde_hdmi_audio_get_audio_sample_rate(u32 *sample_rate_hz) +{ + u32 rate = *sample_rate_hz; + + switch (rate) { + case 32000: + *sample_rate_hz = AUDIO_SAMPLE_RATE_32KHZ; + break; + case 44100: + *sample_rate_hz = AUDIO_SAMPLE_RATE_44_1KHZ; + break; + case 48000: + *sample_rate_hz = AUDIO_SAMPLE_RATE_48KHZ; + break; + case 88200: + *sample_rate_hz = AUDIO_SAMPLE_RATE_88_2KHZ; + break; + case 96000: + *sample_rate_hz = AUDIO_SAMPLE_RATE_96KHZ; + break; + case 176400: + *sample_rate_hz = AUDIO_SAMPLE_RATE_176_4KHZ; + break; + case 192000: + *sample_rate_hz = AUDIO_SAMPLE_RATE_192KHZ; + break; + default: + SDE_ERROR("%d unchanged\n", rate); + break; + } +} + +static void _sde_hdmi_audio_get_acr_param(u32 pclk, u32 fs, + struct hdmi_audio_acr *acr) +{ + u32 div, mul; + + if (!acr) { + SDE_ERROR("invalid data\n"); + return; + } + + /* + * as per HDMI specification, N/CTS = (128*fs)/pclk. + * get the ratio using this formula. + */ + acr->n = HDMI_ACR_N_MULTIPLIER * fs; + acr->cts = pclk; + + /* get the greatest common divisor for the ratio */ + div = gcd(acr->n, acr->cts); + + /* get the n and cts values wrt N/CTS formula */ + acr->n /= div; + acr->cts /= div; + + /* + * as per HDMI specification, 300 <= 128*fs/N <= 1500 + * with a target of 128*fs/N = 1000. To get closest + * value without truncating fractional values, find + * the corresponding multiplier + */ + mul = ((HDMI_ACR_N_MULTIPLIER * fs / HDMI_KHZ_TO_HZ) + + (acr->n - 1)) / acr->n; + + acr->n *= mul; + acr->cts *= mul; +} + +static void _sde_hdmi_audio_acr_enable(struct sde_hdmi_audio *audio) +{ + struct hdmi_audio_acr acr; + struct msm_ext_disp_audio_setup_params *params; + u32 pclk, layout, multiplier = 1, sample_rate; + u32 acr_pkt_ctl, aud_pkt_ctl2, acr_reg_cts, acr_reg_n; + struct hdmi *hdmi; + + hdmi = audio->hdmi; + params = &audio->params; + pclk = audio->pclk; + sample_rate = params->sample_rate_hz; + + _sde_hdmi_audio_get_acr_param(pclk, sample_rate, &acr); + _sde_hdmi_audio_get_audio_sample_rate(&sample_rate); + + layout = (params->num_of_channels == AUDIO_CHANNEL_2) ? 0 : 1; + + SDE_DEBUG("n=%u, cts=%u, layout=%u\n", acr.n, acr.cts, layout); + + /* AUDIO_PRIORITY | SOURCE */ + acr_pkt_ctl = BIT(31) | BIT(8); + + switch (sample_rate) { + case AUDIO_SAMPLE_RATE_44_1KHZ: + acr_pkt_ctl |= 0x2 << 4; + acr.cts <<= 12; + + acr_reg_cts = HDMI_ACR_44_0; + acr_reg_n = HDMI_ACR_44_1; + break; + case AUDIO_SAMPLE_RATE_48KHZ: + acr_pkt_ctl |= 0x3 << 4; + acr.cts <<= 12; + + acr_reg_cts = HDMI_ACR_48_0; + acr_reg_n = HDMI_ACR_48_1; + break; + case AUDIO_SAMPLE_RATE_192KHZ: + multiplier = 4; + acr.n >>= 2; + + acr_pkt_ctl |= 0x3 << 4; + acr.cts <<= 12; + + acr_reg_cts = HDMI_ACR_48_0; + acr_reg_n = HDMI_ACR_48_1; + break; + case AUDIO_SAMPLE_RATE_176_4KHZ: + multiplier = 4; + acr.n >>= 2; + + acr_pkt_ctl |= 0x2 << 4; + acr.cts <<= 12; + + acr_reg_cts = HDMI_ACR_44_0; + acr_reg_n = HDMI_ACR_44_1; + break; + case AUDIO_SAMPLE_RATE_96KHZ: + multiplier = 2; + acr.n >>= 1; + + acr_pkt_ctl |= 0x3 << 4; + acr.cts <<= 12; + + acr_reg_cts = HDMI_ACR_48_0; + acr_reg_n = HDMI_ACR_48_1; + break; + case AUDIO_SAMPLE_RATE_88_2KHZ: + multiplier = 2; + acr.n >>= 1; + + acr_pkt_ctl |= 0x2 << 4; + acr.cts <<= 12; + + acr_reg_cts = HDMI_ACR_44_0; + acr_reg_n = HDMI_ACR_44_1; + break; + default: + multiplier = 1; + + acr_pkt_ctl |= 0x1 << 4; + acr.cts <<= 12; + + acr_reg_cts = HDMI_ACR_32_0; + acr_reg_n = HDMI_ACR_32_1; + break; + } + + aud_pkt_ctl2 = BIT(0) | (layout << 1); + + /* N_MULTIPLE(multiplier) */ + acr_pkt_ctl &= ~(7 << 16); + acr_pkt_ctl |= (multiplier & 0x7) << 16; + + /* SEND | CONT */ + acr_pkt_ctl |= BIT(0) | BIT(1); + + hdmi_write(hdmi, acr_reg_cts, acr.cts); + hdmi_write(hdmi, acr_reg_n, acr.n); + hdmi_write(hdmi, HDMI_ACR_PKT_CTRL, acr_pkt_ctl); + hdmi_write(hdmi, HDMI_AUDIO_PKT_CTRL2, aud_pkt_ctl2); +} + +static void _sde_hdmi_audio_acr_setup(struct sde_hdmi_audio *audio, bool on) +{ + if (on) + _sde_hdmi_audio_acr_enable(audio); + else + hdmi_write(audio->hdmi, HDMI_ACR_PKT_CTRL, 0); +} + +static void _sde_hdmi_audio_infoframe_setup(struct sde_hdmi_audio *audio, + bool enabled) +{ + struct hdmi *hdmi = audio->hdmi; + u32 channels, channel_allocation, level_shift, down_mix, layout; + u32 hdmi_debug_reg = 0, audio_info_0_reg = 0, audio_info_1_reg = 0; + u32 audio_info_ctrl_reg, aud_pck_ctrl_2_reg; + u32 check_sum, sample_present; + + audio_info_ctrl_reg = hdmi_read(hdmi, HDMI_INFOFRAME_CTRL0); + audio_info_ctrl_reg &= ~0xF0; + + if (!enabled) + goto end; + + channels = audio->params.num_of_channels - 1; + channel_allocation = audio->params.channel_allocation; + level_shift = audio->params.level_shift; + down_mix = audio->params.down_mix; + sample_present = audio->params.sample_present; + + layout = (audio->params.num_of_channels == AUDIO_CHANNEL_2) ? 0 : 1; + aud_pck_ctrl_2_reg = BIT(0) | (layout << 1); + hdmi_write(hdmi, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg); + + audio_info_1_reg |= channel_allocation & 0xFF; + audio_info_1_reg |= ((level_shift & 0xF) << 11); + audio_info_1_reg |= ((down_mix & 0x1) << 15); + + check_sum = 0; + check_sum += HDMI_AUDIO_INFO_FRAME_PACKET_HEADER; + check_sum += HDMI_AUDIO_INFO_FRAME_PACKET_VERSION; + check_sum += HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH; + check_sum += channels; + check_sum += channel_allocation; + check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7; + check_sum &= 0xFF; + check_sum = (u8) (256 - check_sum); + + audio_info_0_reg |= check_sum & 0xFF; + audio_info_0_reg |= ((channels & 0x7) << 8); + + /* Enable Audio InfoFrame Transmission */ + audio_info_ctrl_reg |= 0xF0; + + if (layout) { + /* Set the Layout bit */ + hdmi_debug_reg |= BIT(4); + + /* Set the Sample Present bits */ + hdmi_debug_reg |= sample_present & 0xF; + } +end: + hdmi_write(hdmi, HDMI_DEBUG, hdmi_debug_reg); + hdmi_write(hdmi, HDMI_AUDIO_INFO0, audio_info_0_reg); + hdmi_write(hdmi, HDMI_AUDIO_INFO1, audio_info_1_reg); + hdmi_write(hdmi, HDMI_INFOFRAME_CTRL0, audio_info_ctrl_reg); +} + +int sde_hdmi_audio_on(struct hdmi *hdmi, + struct msm_ext_disp_audio_setup_params *params) +{ + struct sde_hdmi_audio audio; + int rc = 0; + + if (!hdmi) { + SDE_ERROR("invalid HDMI Ctrl\n"); + rc = -ENODEV; + goto end; + } + + audio.pclk = hdmi->pixclock; + audio.params = *params; + audio.hdmi = hdmi; + + if (!audio.params.num_of_channels) { + audio.params.sample_rate_hz = DEFAULT_AUDIO_SAMPLE_RATE_HZ; + audio.params.num_of_channels = AUDIO_CHANNEL_2; + } + + _sde_hdmi_audio_acr_setup(&audio, true); + _sde_hdmi_audio_infoframe_setup(&audio, true); + + SDE_DEBUG("HDMI Audio: Enabled\n"); +end: + return rc; +} + +void sde_hdmi_audio_off(struct hdmi *hdmi) +{ + struct sde_hdmi_audio audio; + int rc = 0; + + if (!hdmi) { + SDE_ERROR("invalid HDMI Ctrl\n"); + rc = -ENODEV; + return; + } + + audio.hdmi = hdmi; + + _sde_hdmi_audio_infoframe_setup(&audio, false); + _sde_hdmi_audio_acr_setup(&audio, false); + + SDE_DEBUG("HDMI Audio: Disabled\n"); +} + +int sde_hdmi_config_avmute(struct hdmi *hdmi, bool set) +{ + u32 av_mute_status; + bool av_pkt_en = false; + + if (!hdmi) { + SDE_ERROR("invalid HDMI Ctrl\n"); + return -ENODEV; + } + + av_mute_status = hdmi_read(hdmi, HDMI_GC); + + if (set) { + if (!(av_mute_status & BIT(0))) { + hdmi_write(hdmi, HDMI_GC, av_mute_status | BIT(0)); + av_pkt_en = true; + } + } else { + if (av_mute_status & BIT(0)) { + hdmi_write(hdmi, HDMI_GC, av_mute_status & ~BIT(0)); + av_pkt_en = true; + } + } + + /* Enable AV Mute tranmission here */ + if (av_pkt_en) + hdmi_write(hdmi, HDMI_VBI_PKT_CTRL, + hdmi_read(hdmi, HDMI_VBI_PKT_CTRL) | (BIT(4) & BIT(5))); + + SDE_DEBUG("AVMUTE %s\n", set ? "set" : "cleared"); + + return 0; +} + diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c new file mode 100644 index 000000000000..ecfff7e88689 --- /dev/null +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2013 Red Hat + * Author: Rob Clark <robdclark@gmail.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "drm_edid.h" +#include "sde_kms.h" +#include "sde_hdmi.h" +#include "hdmi.h" + +struct sde_hdmi_bridge { + struct drm_bridge base; + struct hdmi *hdmi; +}; +#define to_hdmi_bridge(x) container_of(x, struct sde_hdmi_bridge, base) + +/* for AVI program */ +#define HDMI_AVI_INFOFRAME_BUFFER_SIZE \ + (HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE) +#define HDMI_VS_INFOFRAME_BUFFER_SIZE (HDMI_INFOFRAME_HEADER_SIZE + 6) +#define HDMI_SPD_INFOFRAME_BUFFER_SIZE \ + (HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE) +#define HDMI_DEFAULT_VENDOR_NAME "unknown" +#define HDMI_DEFAULT_PRODUCT_NAME "msm" +#define LEFT_SHIFT_BYTE(x) ((x) << 8) +#define LEFT_SHIFT_WORD(x) ((x) << 16) +#define LEFT_SHIFT_24BITS(x) ((x) << 24) +#define HDMI_AVI_IFRAME_LINE_NUMBER 1 +#define HDMI_VENDOR_IFRAME_LINE_NUMBER 3 + +void _sde_hdmi_bridge_destroy(struct drm_bridge *bridge) +{ +} + +static void _sde_hdmi_bridge_power_on(struct drm_bridge *bridge) +{ + struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + const struct hdmi_platform_config *config = hdmi->config; + int i, ret; + + for (i = 0; i < config->pwr_reg_cnt; i++) { + ret = regulator_enable(hdmi->pwr_regs[i]); + if (ret) { + SDE_ERROR("failed to enable pwr regulator: %s (%d)\n", + config->pwr_reg_names[i], ret); + } + } + + if (config->pwr_clk_cnt > 0) { + DRM_DEBUG("pixclock: %lu", hdmi->pixclock); + ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock); + if (ret) { + SDE_ERROR("failed to set pixel clk: %s (%d)\n", + config->pwr_clk_names[0], ret); + } + } + + for (i = 0; i < config->pwr_clk_cnt; i++) { + ret = clk_prepare_enable(hdmi->pwr_clks[i]); + if (ret) { + SDE_ERROR("failed to enable pwr clk: %s (%d)\n", + config->pwr_clk_names[i], ret); + } + } +} + +static void _sde_hdmi_bridge_power_off(struct drm_bridge *bridge) +{ + struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + const struct hdmi_platform_config *config = hdmi->config; + int i, ret; + + /* Wait for vsync */ + msleep(20); + + for (i = 0; i < config->pwr_clk_cnt; i++) + clk_disable_unprepare(hdmi->pwr_clks[i]); + + for (i = 0; i < config->pwr_reg_cnt; i++) { + ret = regulator_disable(hdmi->pwr_regs[i]); + if (ret) { + SDE_ERROR("failed to disable pwr regulator: %s (%d)\n", + config->pwr_reg_names[i], ret); + } + } +} + +static void _sde_hdmi_bridge_pre_enable(struct drm_bridge *bridge) +{ + struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + struct hdmi_phy *phy = hdmi->phy; + + DRM_DEBUG("power up"); + + if (!hdmi->power_on) { + _sde_hdmi_bridge_power_on(bridge); + hdmi->power_on = true; + hdmi_audio_update(hdmi); + } + + if (phy) + phy->funcs->powerup(phy, hdmi->pixclock); + + sde_hdmi_set_mode(hdmi, true); + + if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported) + hdmi_hdcp_ctrl_on(hdmi->hdcp_ctrl); +} + +static void _sde_hdmi_bridge_enable(struct drm_bridge *bridge) +{ +} + +static void _sde_hdmi_bridge_disable(struct drm_bridge *bridge) +{ +} + +static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge) +{ + struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + struct hdmi_phy *phy = hdmi->phy; + + if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported) + hdmi_hdcp_ctrl_off(hdmi->hdcp_ctrl); + + DRM_DEBUG("power down"); + sde_hdmi_set_mode(hdmi, false); + + if (phy) + phy->funcs->powerdown(phy); + + if (hdmi->power_on) { + _sde_hdmi_bridge_power_off(bridge); + hdmi->power_on = false; + hdmi_audio_update(hdmi); + } +} + +static void _sde_hdmi_bridge_set_avi_infoframe(struct hdmi *hdmi, + const struct drm_display_mode *mode) +{ + u8 avi_iframe[HDMI_AVI_INFOFRAME_BUFFER_SIZE] = {0}; + u8 *avi_frame = &avi_iframe[HDMI_INFOFRAME_HEADER_SIZE]; + u8 checksum; + u32 reg_val; + struct hdmi_avi_infoframe info; + + drm_hdmi_avi_infoframe_from_display_mode(&info, mode); + hdmi_avi_infoframe_pack(&info, avi_iframe, sizeof(avi_iframe)); + checksum = avi_iframe[HDMI_INFOFRAME_HEADER_SIZE - 1]; + + reg_val = checksum | + LEFT_SHIFT_BYTE(avi_frame[0]) | + LEFT_SHIFT_WORD(avi_frame[1]) | + LEFT_SHIFT_24BITS(avi_frame[2]); + hdmi_write(hdmi, REG_HDMI_AVI_INFO(0), reg_val); + + reg_val = avi_frame[3] | + LEFT_SHIFT_BYTE(avi_frame[4]) | + LEFT_SHIFT_WORD(avi_frame[5]) | + LEFT_SHIFT_24BITS(avi_frame[6]); + hdmi_write(hdmi, REG_HDMI_AVI_INFO(1), reg_val); + + reg_val = avi_frame[7] | + LEFT_SHIFT_BYTE(avi_frame[8]) | + LEFT_SHIFT_WORD(avi_frame[9]) | + LEFT_SHIFT_24BITS(avi_frame[10]); + hdmi_write(hdmi, REG_HDMI_AVI_INFO(2), reg_val); + + reg_val = avi_frame[11] | + LEFT_SHIFT_BYTE(avi_frame[12]) | + LEFT_SHIFT_24BITS(avi_iframe[1]); + hdmi_write(hdmi, REG_HDMI_AVI_INFO(3), reg_val); + + /* AVI InfFrame enable (every frame) */ + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, + hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0)); + + reg_val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + reg_val &= ~0x3F; + reg_val |= HDMI_AVI_IFRAME_LINE_NUMBER; + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, reg_val); +} + +static void _sde_hdmi_bridge_set_vs_infoframe(struct hdmi *hdmi, + const struct drm_display_mode *mode) +{ + u8 vs_iframe[HDMI_VS_INFOFRAME_BUFFER_SIZE] = {0}; + u32 reg_val; + struct hdmi_vendor_infoframe info; + int rc = 0; + + rc = drm_hdmi_vendor_infoframe_from_display_mode(&info, mode); + if (rc < 0) { + SDE_DEBUG("don't send vendor infoframe\n"); + return; + } + hdmi_vendor_infoframe_pack(&info, vs_iframe, sizeof(vs_iframe)); + + reg_val = (info.s3d_struct << 24) | (info.vic << 16) | + (vs_iframe[3] << 8) | (vs_iframe[7] << 5) | + vs_iframe[2]; + hdmi_write(hdmi, REG_HDMI_VENSPEC_INFO0, reg_val); + + /* vendor specific info-frame enable (every frame) */ + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, + hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0) | BIT(13) | BIT(12)); + + reg_val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + reg_val &= ~0x3F000000; + reg_val |= (HDMI_VENDOR_IFRAME_LINE_NUMBER << 24); + hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, reg_val); +} + +static void _sde_hdmi_bridge_set_spd_infoframe(struct hdmi *hdmi, + const struct drm_display_mode *mode) +{ + u8 spd_iframe[HDMI_SPD_INFOFRAME_BUFFER_SIZE] = {0}; + u32 packet_payload, packet_control, packet_header; + struct hdmi_spd_infoframe info; + int i; + + /* Need to query vendor and product name from platform setup */ + hdmi_spd_infoframe_init(&info, HDMI_DEFAULT_VENDOR_NAME, + HDMI_DEFAULT_PRODUCT_NAME); + hdmi_spd_infoframe_pack(&info, spd_iframe, sizeof(spd_iframe)); + + packet_header = spd_iframe[0] + | LEFT_SHIFT_BYTE(spd_iframe[1] & 0x7f) + | LEFT_SHIFT_WORD(spd_iframe[2] & 0x7f); + hdmi_write(hdmi, REG_HDMI_GENERIC1_HDR, packet_header); + + for (i = 0; i < MAX_REG_HDMI_GENERIC1_INDEX; i++) { + packet_payload = spd_iframe[3 + i * 4] + | LEFT_SHIFT_BYTE(spd_iframe[4 + i * 4] & 0x7f) + | LEFT_SHIFT_WORD(spd_iframe[5 + i * 4] & 0x7f) + | LEFT_SHIFT_24BITS(spd_iframe[6 + i * 4] & 0x7f); + hdmi_write(hdmi, REG_HDMI_GENERIC1(i), packet_payload); + } + + packet_payload = (spd_iframe[27] & 0x7f) + | LEFT_SHIFT_BYTE(spd_iframe[28] & 0x7f); + hdmi_write(hdmi, REG_HDMI_GENERIC1(MAX_REG_HDMI_GENERIC1_INDEX), + packet_payload); + + /* + * GENERIC1_LINE | GENERIC1_CONT | GENERIC1_SEND + * Setup HDMI TX generic packet control + * Enable this packet to transmit every frame + * Enable HDMI TX engine to transmit Generic packet 1 + */ + packet_control = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL); + packet_control |= ((0x1 << 24) | (1 << 5) | (1 << 4)); + hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, packet_control); +} + +static void _sde_hdmi_bridge_mode_set(struct drm_bridge *bridge, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + int hstart, hend, vstart, vend; + uint32_t frame_ctrl; + + mode = adjusted_mode; + + hdmi->pixclock = mode->clock * 1000; + + hstart = mode->htotal - mode->hsync_start; + hend = mode->htotal - mode->hsync_start + mode->hdisplay; + + vstart = mode->vtotal - mode->vsync_start - 1; + vend = mode->vtotal - mode->vsync_start + mode->vdisplay - 1; + + DRM_DEBUG( + "htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d", + mode->htotal, mode->vtotal, hstart, hend, vstart, vend); + + hdmi_write(hdmi, REG_HDMI_TOTAL, + HDMI_TOTAL_H_TOTAL(mode->htotal - 1) | + HDMI_TOTAL_V_TOTAL(mode->vtotal - 1)); + + hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC, + HDMI_ACTIVE_HSYNC_START(hstart) | + HDMI_ACTIVE_HSYNC_END(hend)); + hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC, + HDMI_ACTIVE_VSYNC_START(vstart) | + HDMI_ACTIVE_VSYNC_END(vend)); + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2, + HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal)); + hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2, + HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) | + HDMI_VSYNC_ACTIVE_F2_END(vend + 1)); + } else { + hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2, + HDMI_VSYNC_TOTAL_F2_V_TOTAL(0)); + hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2, + HDMI_VSYNC_ACTIVE_F2_START(0) | + HDMI_VSYNC_ACTIVE_F2_END(0)); + } + + frame_ctrl = 0; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN; + DRM_DEBUG("frame_ctrl=%08x\n", frame_ctrl); + hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); + + /* + * Setup info frame + * Current drm_edid driver doesn't have all CEA formats defined in + * latest CEA-861(CTA-861) spec. So, don't check if mode is CEA mode + * in here. Once core framework is updated, the check needs to be + * added back. + */ + if (hdmi->hdmi_mode) { + _sde_hdmi_bridge_set_avi_infoframe(hdmi, mode); + _sde_hdmi_bridge_set_vs_infoframe(hdmi, mode); + _sde_hdmi_bridge_set_spd_infoframe(hdmi, mode); + DRM_DEBUG("hdmi setup info frame\n"); + } + + hdmi_audio_update(hdmi); +} + +static const struct drm_bridge_funcs _sde_hdmi_bridge_funcs = { + .pre_enable = _sde_hdmi_bridge_pre_enable, + .enable = _sde_hdmi_bridge_enable, + .disable = _sde_hdmi_bridge_disable, + .post_disable = _sde_hdmi_bridge_post_disable, + .mode_set = _sde_hdmi_bridge_mode_set, +}; + + +/* initialize bridge */ +struct drm_bridge *sde_hdmi_bridge_init(struct hdmi *hdmi) +{ + struct drm_bridge *bridge = NULL; + struct sde_hdmi_bridge *sde_hdmi_bridge; + int ret; + + sde_hdmi_bridge = devm_kzalloc(hdmi->dev->dev, + sizeof(*sde_hdmi_bridge), GFP_KERNEL); + if (!sde_hdmi_bridge) { + ret = -ENOMEM; + goto fail; + } + + sde_hdmi_bridge->hdmi = hdmi; + + bridge = &sde_hdmi_bridge->base; + bridge->funcs = &_sde_hdmi_bridge_funcs; + + ret = drm_bridge_attach(hdmi->dev, bridge); + if (ret) + goto fail; + + return bridge; + +fail: + if (bridge) + _sde_hdmi_bridge_destroy(bridge); + + return ERR_PTR(ret); +} diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_regs.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_regs.h new file mode 100644 index 000000000000..f1bff0f08051 --- /dev/null +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_regs.h @@ -0,0 +1,300 @@ +/* Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SDE_HDMI_REGS_H +#define _SDE_HDMI_REGS_H + +/* HDMI_TX Registers */ +#define HDMI_CTRL (0x00000000) +#define HDMI_TEST_PATTERN (0x00000010) +#define HDMI_RANDOM_PATTERN (0x00000014) +#define HDMI_PKT_BLK_CTRL (0x00000018) +#define HDMI_STATUS (0x0000001C) +#define HDMI_AUDIO_PKT_CTRL (0x00000020) +#define HDMI_ACR_PKT_CTRL (0x00000024) +#define HDMI_VBI_PKT_CTRL (0x00000028) +#define HDMI_INFOFRAME_CTRL0 (0x0000002C) +#define HDMI_INFOFRAME_CTRL1 (0x00000030) +#define HDMI_GEN_PKT_CTRL (0x00000034) +#define HDMI_ACP (0x0000003C) +#define HDMI_GC (0x00000040) +#define HDMI_AUDIO_PKT_CTRL2 (0x00000044) +#define HDMI_ISRC1_0 (0x00000048) +#define HDMI_ISRC1_1 (0x0000004C) +#define HDMI_ISRC1_2 (0x00000050) +#define HDMI_ISRC1_3 (0x00000054) +#define HDMI_ISRC1_4 (0x00000058) +#define HDMI_ISRC2_0 (0x0000005C) +#define HDMI_ISRC2_1 (0x00000060) +#define HDMI_ISRC2_2 (0x00000064) +#define HDMI_ISRC2_3 (0x00000068) +#define HDMI_AVI_INFO0 (0x0000006C) +#define HDMI_AVI_INFO1 (0x00000070) +#define HDMI_AVI_INFO2 (0x00000074) +#define HDMI_AVI_INFO3 (0x00000078) +#define HDMI_MPEG_INFO0 (0x0000007C) +#define HDMI_MPEG_INFO1 (0x00000080) +#define HDMI_GENERIC0_HDR (0x00000084) +#define HDMI_GENERIC0_0 (0x00000088) +#define HDMI_GENERIC0_1 (0x0000008C) +#define HDMI_GENERIC0_2 (0x00000090) +#define HDMI_GENERIC0_3 (0x00000094) +#define HDMI_GENERIC0_4 (0x00000098) +#define HDMI_GENERIC0_5 (0x0000009C) +#define HDMI_GENERIC0_6 (0x000000A0) +#define HDMI_GENERIC1_HDR (0x000000A4) +#define HDMI_GENERIC1_0 (0x000000A8) +#define HDMI_GENERIC1_1 (0x000000AC) +#define HDMI_GENERIC1_2 (0x000000B0) +#define HDMI_GENERIC1_3 (0x000000B4) +#define HDMI_GENERIC1_4 (0x000000B8) +#define HDMI_GENERIC1_5 (0x000000BC) +#define HDMI_GENERIC1_6 (0x000000C0) +#define HDMI_ACR_32_0 (0x000000C4) +#define HDMI_ACR_32_1 (0x000000C8) +#define HDMI_ACR_44_0 (0x000000CC) +#define HDMI_ACR_44_1 (0x000000D0) +#define HDMI_ACR_48_0 (0x000000D4) +#define HDMI_ACR_48_1 (0x000000D8) +#define HDMI_ACR_STATUS_0 (0x000000DC) +#define HDMI_ACR_STATUS_1 (0x000000E0) +#define HDMI_AUDIO_INFO0 (0x000000E4) +#define HDMI_AUDIO_INFO1 (0x000000E8) +#define HDMI_CS_60958_0 (0x000000EC) +#define HDMI_CS_60958_1 (0x000000F0) +#define HDMI_RAMP_CTRL0 (0x000000F8) +#define HDMI_RAMP_CTRL1 (0x000000FC) +#define HDMI_RAMP_CTRL2 (0x00000100) +#define HDMI_RAMP_CTRL3 (0x00000104) +#define HDMI_CS_60958_2 (0x00000108) +#define HDMI_HDCP_CTRL2 (0x0000010C) +#define HDMI_HDCP_CTRL (0x00000110) +#define HDMI_HDCP_DEBUG_CTRL (0x00000114) +#define HDMI_HDCP_INT_CTRL (0x00000118) +#define HDMI_HDCP_LINK0_STATUS (0x0000011C) +#define HDMI_HDCP_DDC_CTRL_0 (0x00000120) +#define HDMI_HDCP_DDC_CTRL_1 (0x00000124) +#define HDMI_HDCP_DDC_STATUS (0x00000128) +#define HDMI_HDCP_ENTROPY_CTRL0 (0x0000012C) +#define HDMI_HDCP_RESET (0x00000130) +#define HDMI_HDCP_RCVPORT_DATA0 (0x00000134) +#define HDMI_HDCP_RCVPORT_DATA1 (0x00000138) +#define HDMI_HDCP_RCVPORT_DATA2_0 (0x0000013C) +#define HDMI_HDCP_RCVPORT_DATA2_1 (0x00000140) +#define HDMI_HDCP_RCVPORT_DATA3 (0x00000144) +#define HDMI_HDCP_RCVPORT_DATA4 (0x00000148) +#define HDMI_HDCP_RCVPORT_DATA5 (0x0000014C) +#define HDMI_HDCP_RCVPORT_DATA6 (0x00000150) +#define HDMI_HDCP_RCVPORT_DATA7 (0x00000154) +#define HDMI_HDCP_RCVPORT_DATA8 (0x00000158) +#define HDMI_HDCP_RCVPORT_DATA9 (0x0000015C) +#define HDMI_HDCP_RCVPORT_DATA10 (0x00000160) +#define HDMI_HDCP_RCVPORT_DATA11 (0x00000164) +#define HDMI_HDCP_RCVPORT_DATA12 (0x00000168) +#define HDMI_VENSPEC_INFO0 (0x0000016C) +#define HDMI_VENSPEC_INFO1 (0x00000170) +#define HDMI_VENSPEC_INFO2 (0x00000174) +#define HDMI_VENSPEC_INFO3 (0x00000178) +#define HDMI_VENSPEC_INFO4 (0x0000017C) +#define HDMI_VENSPEC_INFO5 (0x00000180) +#define HDMI_VENSPEC_INFO6 (0x00000184) +#define HDMI_HDCP_DEBUG (0x00000194) +#define HDMI_TMDS_CTRL_CHAR (0x0000019C) +#define HDMI_TMDS_CTRL_SEL (0x000001A4) +#define HDMI_TMDS_SYNCCHAR01 (0x000001A8) +#define HDMI_TMDS_SYNCCHAR23 (0x000001AC) +#define HDMI_TMDS_DEBUG (0x000001B4) +#define HDMI_TMDS_CTL_BITS (0x000001B8) +#define HDMI_TMDS_DCBAL_CTRL (0x000001BC) +#define HDMI_TMDS_DCBAL_CHAR (0x000001C0) +#define HDMI_TMDS_CTL01_GEN (0x000001C8) +#define HDMI_TMDS_CTL23_GEN (0x000001CC) +#define HDMI_AUDIO_CFG (0x000001D0) +#define HDMI_DEBUG (0x00000204) +#define HDMI_USEC_REFTIMER (0x00000208) +#define HDMI_DDC_CTRL (0x0000020C) +#define HDMI_DDC_ARBITRATION (0x00000210) +#define HDMI_DDC_INT_CTRL (0x00000214) +#define HDMI_DDC_SW_STATUS (0x00000218) +#define HDMI_DDC_HW_STATUS (0x0000021C) +#define HDMI_DDC_SPEED (0x00000220) +#define HDMI_DDC_SETUP (0x00000224) +#define HDMI_DDC_TRANS0 (0x00000228) +#define HDMI_DDC_TRANS1 (0x0000022C) +#define HDMI_DDC_TRANS2 (0x00000230) +#define HDMI_DDC_TRANS3 (0x00000234) +#define HDMI_DDC_DATA (0x00000238) +#define HDMI_HDCP_SHA_CTRL (0x0000023C) +#define HDMI_HDCP_SHA_STATUS (0x00000240) +#define HDMI_HDCP_SHA_DATA (0x00000244) +#define HDMI_HDCP_SHA_DBG_M0_0 (0x00000248) +#define HDMI_HDCP_SHA_DBG_M0_1 (0x0000024C) +#define HDMI_HPD_INT_STATUS (0x00000250) +#define HDMI_HPD_INT_CTRL (0x00000254) +#define HDMI_HPD_CTRL (0x00000258) +#define HDMI_HDCP_ENTROPY_CTRL1 (0x0000025C) +#define HDMI_HDCP_SW_UPPER_AN (0x00000260) +#define HDMI_HDCP_SW_LOWER_AN (0x00000264) +#define HDMI_CRC_CTRL (0x00000268) +#define HDMI_VID_CRC (0x0000026C) +#define HDMI_AUD_CRC (0x00000270) +#define HDMI_VBI_CRC (0x00000274) +#define HDMI_DDC_REF (0x0000027C) +#define HDMI_HDCP_SW_UPPER_AKSV (0x00000284) +#define HDMI_HDCP_SW_LOWER_AKSV (0x00000288) +#define HDMI_CEC_CTRL (0x0000028C) +#define HDMI_CEC_WR_DATA (0x00000290) +#define HDMI_CEC_RETRANSMIT (0x00000294) +#define HDMI_CEC_STATUS (0x00000298) +#define HDMI_CEC_INT (0x0000029C) +#define HDMI_CEC_ADDR (0x000002A0) +#define HDMI_CEC_TIME (0x000002A4) +#define HDMI_CEC_REFTIMER (0x000002A8) +#define HDMI_CEC_RD_DATA (0x000002AC) +#define HDMI_CEC_RD_FILTER (0x000002B0) +#define HDMI_ACTIVE_H (0x000002B4) +#define HDMI_ACTIVE_V (0x000002B8) +#define HDMI_ACTIVE_V_F2 (0x000002BC) +#define HDMI_TOTAL (0x000002C0) +#define HDMI_V_TOTAL_F2 (0x000002C4) +#define HDMI_FRAME_CTRL (0x000002C8) +#define HDMI_AUD_INT (0x000002CC) +#define HDMI_DEBUG_BUS_CTRL (0x000002D0) +#define HDMI_PHY_CTRL (0x000002D4) +#define HDMI_CEC_WR_RANGE (0x000002DC) +#define HDMI_CEC_RD_RANGE (0x000002E0) +#define HDMI_VERSION (0x000002E4) +#define HDMI_BIST_ENABLE (0x000002F4) +#define HDMI_TIMING_ENGINE_EN (0x000002F8) +#define HDMI_INTF_CONFIG (0x000002FC) +#define HDMI_HSYNC_CTL (0x00000300) +#define HDMI_VSYNC_PERIOD_F0 (0x00000304) +#define HDMI_VSYNC_PERIOD_F1 (0x00000308) +#define HDMI_VSYNC_PULSE_WIDTH_F0 (0x0000030C) +#define HDMI_VSYNC_PULSE_WIDTH_F1 (0x00000310) +#define HDMI_DISPLAY_V_START_F0 (0x00000314) +#define HDMI_DISPLAY_V_START_F1 (0x00000318) +#define HDMI_DISPLAY_V_END_F0 (0x0000031C) +#define HDMI_DISPLAY_V_END_F1 (0x00000320) +#define HDMI_ACTIVE_V_START_F0 (0x00000324) +#define HDMI_ACTIVE_V_START_F1 (0x00000328) +#define HDMI_ACTIVE_V_END_F0 (0x0000032C) +#define HDMI_ACTIVE_V_END_F1 (0x00000330) +#define HDMI_DISPLAY_HCTL (0x00000334) +#define HDMI_ACTIVE_HCTL (0x00000338) +#define HDMI_HSYNC_SKEW (0x0000033C) +#define HDMI_POLARITY_CTL (0x00000340) +#define HDMI_TPG_MAIN_CONTROL (0x00000344) +#define HDMI_TPG_VIDEO_CONFIG (0x00000348) +#define HDMI_TPG_COMPONENT_LIMITS (0x0000034C) +#define HDMI_TPG_RECTANGLE (0x00000350) +#define HDMI_TPG_INITIAL_VALUE (0x00000354) +#define HDMI_TPG_BLK_WHT_PATTERN_FRAMES (0x00000358) +#define HDMI_TPG_RGB_MAPPING (0x0000035C) +#define HDMI_CEC_COMPL_CTL (0x00000360) +#define HDMI_CEC_RD_START_RANGE (0x00000364) +#define HDMI_CEC_RD_TOTAL_RANGE (0x00000368) +#define HDMI_CEC_RD_ERR_RESP_LO (0x0000036C) +#define HDMI_CEC_WR_CHECK_CONFIG (0x00000370) +#define HDMI_INTERNAL_TIMING_MODE (0x00000374) +#define HDMI_CTRL_SW_RESET (0x00000378) +#define HDMI_CTRL_AUDIO_RESET (0x0000037C) +#define HDMI_SCRATCH (0x00000380) +#define HDMI_CLK_CTRL (0x00000384) +#define HDMI_CLK_ACTIVE (0x00000388) +#define HDMI_VBI_CFG (0x0000038C) +#define HDMI_DDC_INT_CTRL0 (0x00000430) +#define HDMI_DDC_INT_CTRL1 (0x00000434) +#define HDMI_DDC_INT_CTRL2 (0x00000438) +#define HDMI_DDC_INT_CTRL3 (0x0000043C) +#define HDMI_DDC_INT_CTRL4 (0x00000440) +#define HDMI_DDC_INT_CTRL5 (0x00000444) +#define HDMI_HDCP2P2_DDC_CTRL (0x0000044C) +#define HDMI_HDCP2P2_DDC_TIMER_CTRL (0x00000450) +#define HDMI_HDCP2P2_DDC_TIMER_CTRL2 (0x00000454) +#define HDMI_HDCP2P2_DDC_STATUS (0x00000458) +#define HDMI_SCRAMBLER_STATUS_DDC_CTRL (0x00000464) +#define HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL (0x00000468) +#define HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL2 (0x0000046C) +#define HDMI_SCRAMBLER_STATUS_DDC_STATUS (0x00000470) +#define HDMI_SCRAMBLER_STATUS_DDC_TIMER_STATUS (0x00000474) +#define HDMI_SCRAMBLER_STATUS_DDC_TIMER_STATUS2 (0x00000478) +#define HDMI_HW_DDC_CTRL (0x000004CC) +#define HDMI_HDCP2P2_DDC_SW_TRIGGER (0x000004D0) +#define HDMI_HDCP_STATUS (0x00000500) +#define HDMI_HDCP_INT_CTRL2 (0x00000504) + +/* HDMI PHY Registers */ +#define HDMI_PHY_ANA_CFG0 (0x00000000) +#define HDMI_PHY_ANA_CFG1 (0x00000004) +#define HDMI_PHY_PD_CTRL0 (0x00000010) +#define HDMI_PHY_PD_CTRL1 (0x00000014) +#define HDMI_PHY_BIST_CFG0 (0x00000034) +#define HDMI_PHY_BIST_PATN0 (0x0000003C) +#define HDMI_PHY_BIST_PATN1 (0x00000040) +#define HDMI_PHY_BIST_PATN2 (0x00000044) +#define HDMI_PHY_BIST_PATN3 (0x00000048) + +/* QFPROM Registers for HDMI/HDCP */ +#define QFPROM_RAW_FEAT_CONFIG_ROW0_LSB (0x000000F8) +#define QFPROM_RAW_FEAT_CONFIG_ROW0_MSB (0x000000FC) +#define QFPROM_RAW_VERSION_4 (0x000000A8) +#define SEC_CTRL_HW_VERSION (0x00006000) +#define HDCP_KSV_LSB (0x000060D8) +#define HDCP_KSV_MSB (0x000060DC) +#define HDCP_KSV_VERSION_4_OFFSET (0x00000014) + +/* SEC_CTRL version that supports HDCP SEL */ +#define HDCP_SEL_MIN_SEC_VERSION (0x50010000) + +#define LPASS_LPAIF_RDDMA_CTL0 (0xFE152000) +#define LPASS_LPAIF_RDDMA_PER_CNT0 (0x00000014) + +/* TX major version that supports scrambling */ +#define HDMI_TX_SCRAMBLER_MIN_TX_VERSION 0x04 + +/* TX major versions */ +#define HDMI_TX_VERSION_4 4 +#define HDMI_TX_VERSION_3 3 + +/* HDMI SCDC register offsets */ +#define HDMI_SCDC_UPDATE_0 0x10 +#define HDMI_SCDC_UPDATE_1 0x11 +#define HDMI_SCDC_TMDS_CONFIG 0x20 +#define HDMI_SCDC_SCRAMBLER_STATUS 0x21 +#define HDMI_SCDC_CONFIG_0 0x30 +#define HDMI_SCDC_STATUS_FLAGS_0 0x40 +#define HDMI_SCDC_STATUS_FLAGS_1 0x41 +#define HDMI_SCDC_ERR_DET_0_L 0x50 +#define HDMI_SCDC_ERR_DET_0_H 0x51 +#define HDMI_SCDC_ERR_DET_1_L 0x52 +#define HDMI_SCDC_ERR_DET_1_H 0x53 +#define HDMI_SCDC_ERR_DET_2_L 0x54 +#define HDMI_SCDC_ERR_DET_2_H 0x55 +#define HDMI_SCDC_ERR_DET_CHECKSUM 0x56 + +/* HDCP secure registers directly accessible to HLOS since HDMI controller + * version major version 4.0 + */ +#define HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA0 (0x00000004) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA1 (0x00000008) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA7 (0x0000000C) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA8 (0x00000010) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA9 (0x00000014) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA10 (0x00000018) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x0000001C) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x00000020) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_CTRL (0x00000024) +#define HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_DATA (0x00000028) + +#endif /* _SDE_HDMI_REGS_H */ + diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h index 767debc02f36..aef20f76bf02 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h @@ -111,6 +111,8 @@ static inline uint32_t HDMI_ACR_PKT_CTRL_N_MULTIPLIER(uint32_t val) #define HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE 0x00000040 #define HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE 0x00000080 +#define REG_HDMI_INFOFRAME_CTRL1 0x00000030 + #define REG_HDMI_GEN_PKT_CTRL 0x00000034 #define HDMI_GEN_PKT_CTRL_GENERIC0_SEND 0x00000001 #define HDMI_GEN_PKT_CTRL_GENERIC0_CONT 0x00000002 @@ -150,6 +152,7 @@ static inline uint32_t REG_HDMI_GENERIC0(uint32_t i0) { return 0x00000088 + 0x4* #define REG_HDMI_GENERIC1_HDR 0x000000a4 +#define MAX_REG_HDMI_GENERIC1_INDEX 6 static inline uint32_t REG_HDMI_GENERIC1(uint32_t i0) { return 0x000000a8 + 0x4*i0; } static inline uint32_t REG_HDMI_ACR(enum hdmi_acr_cts i0) { return 0x000000c4 + 0x8*i0; } |
