| From d88a2db7f7ef0a231ef5fc7b91b01f6400ce4d27 Mon Sep 17 00:00:00 2001 |
| From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Date: Fri, 10 Mar 2017 15:48:12 +0530 |
| Subject: [PATCH 234/286] drm: bridge: dw-hdmi: Move the driver to a separate |
| directory. |
| |
| The driver is already made of 5 separate source files. Move it to a |
| newly created directory named synopsys where more Synopsys bridge |
| drivers can be added later (for the DisplayPort controller for |
| instance). |
| |
| Suggested-by: Jose Abreu <Jose.Abreu@synopsys.com> |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Reviewed-by: Jose Abreu <joabreu@synopsys.com> |
| Signed-off-by: Archit Taneja <architt@codeaurora.org> |
| Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-10-laurent.pinchart+renesas@ideasonboard.com |
| (cherry picked from commit 35dc8aabc8783d6322a59d774af2858e5955d2ab) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/gpu/drm/bridge/Kconfig | 25 ++-------------------- |
| drivers/gpu/drm/bridge/Makefile | 4 +--- |
| drivers/gpu/drm/bridge/synopsys/Kconfig | 23 ++++++++++++++++++++ |
| drivers/gpu/drm/bridge/synopsys/Makefile | 5 +++++ |
| .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c | 0 |
| .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h | 0 |
| .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c | 0 |
| drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c | 0 |
| drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h | 0 |
| drivers/gpu/drm/bridge/Kconfig | 25 |
| drivers/gpu/drm/bridge/Makefile | 4 |
| drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c | 652 ----- |
| drivers/gpu/drm/bridge/dw-hdmi-audio.h | 21 |
| drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c | 141 - |
| drivers/gpu/drm/bridge/dw-hdmi.c | 2314 -------------------- |
| drivers/gpu/drm/bridge/dw-hdmi.h | 1153 --------- |
| drivers/gpu/drm/bridge/synopsys/Kconfig | 23 |
| drivers/gpu/drm/bridge/synopsys/Makefile | 5 |
| drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c | 652 +++++ |
| drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 21 |
| drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 141 + |
| drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2314 ++++++++++++++++++++ |
| drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1153 +++++++++ |
| 14 files changed, 4312 insertions(+), 4307 deletions(-) |
| create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig |
| create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile |
| rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%) |
| rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%) |
| rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%) |
| rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (100%) |
| rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%) |
| |
| --- a/drivers/gpu/drm/bridge/Kconfig |
| +++ b/drivers/gpu/drm/bridge/Kconfig |
| @@ -24,29 +24,6 @@ config DRM_DUMB_VGA_DAC |
| help |
| Support for RGB to VGA DAC based bridges |
| |
| -config DRM_DW_HDMI |
| - tristate |
| - select DRM_KMS_HELPER |
| - |
| -config DRM_DW_HDMI_AHB_AUDIO |
| - tristate "Synopsis Designware AHB Audio interface" |
| - depends on DRM_DW_HDMI && SND |
| - select SND_PCM |
| - select SND_PCM_ELD |
| - select SND_PCM_IEC958 |
| - help |
| - Support the AHB Audio interface which is part of the Synopsis |
| - Designware HDMI block. This is used in conjunction with |
| - the i.MX6 HDMI driver. |
| - |
| -config DRM_DW_HDMI_I2S_AUDIO |
| - tristate "Synopsis Designware I2S Audio interface" |
| - depends on DRM_DW_HDMI |
| - select SND_SOC_HDMI_CODEC |
| - help |
| - Support the I2S Audio interface which is part of the Synopsis |
| - Designware HDMI block. |
| - |
| config DRM_NXP_PTN3460 |
| tristate "NXP PTN3460 DP/LVDS bridge" |
| depends on OF |
| @@ -86,4 +63,6 @@ source "drivers/gpu/drm/bridge/analogix/ |
| |
| source "drivers/gpu/drm/bridge/adv7511/Kconfig" |
| |
| +source "drivers/gpu/drm/bridge/synopsys/Kconfig" |
| + |
| endmenu |
| --- a/drivers/gpu/drm/bridge/Makefile |
| +++ b/drivers/gpu/drm/bridge/Makefile |
| @@ -2,12 +2,10 @@ ccflags-y := -Iinclude/drm |
| |
| obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o |
| obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o |
| -obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o |
| -obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o |
| -obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o |
| obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o |
| obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o |
| obj-$(CONFIG_DRM_SII902X) += sii902x.o |
| obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o |
| obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ |
| obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ |
| +obj-y += synopsys/ |
| --- a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c |
| +++ /dev/null |
| @@ -1,652 +0,0 @@ |
| -/* |
| - * DesignWare HDMI audio driver |
| - * |
| - * 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. |
| - * |
| - * Written and tested against the Designware HDMI Tx found in iMX6. |
| - */ |
| -#include <linux/io.h> |
| -#include <linux/interrupt.h> |
| -#include <linux/module.h> |
| -#include <linux/platform_device.h> |
| -#include <drm/bridge/dw_hdmi.h> |
| -#include <drm/drm_edid.h> |
| - |
| -#include <sound/asoundef.h> |
| -#include <sound/core.h> |
| -#include <sound/initval.h> |
| -#include <sound/pcm.h> |
| -#include <sound/pcm_drm_eld.h> |
| -#include <sound/pcm_iec958.h> |
| - |
| -#include "dw-hdmi-audio.h" |
| - |
| -#define DRIVER_NAME "dw-hdmi-ahb-audio" |
| - |
| -/* Provide some bits rather than bit offsets */ |
| -enum { |
| - HDMI_AHB_DMA_CONF0_SW_FIFO_RST = BIT(7), |
| - HDMI_AHB_DMA_CONF0_EN_HLOCK = BIT(3), |
| - HDMI_AHB_DMA_START_START = BIT(0), |
| - HDMI_AHB_DMA_STOP_STOP = BIT(0), |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = BIT(5), |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = BIT(4), |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = BIT(3), |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = BIT(2), |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = BIT(1), |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0), |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL = |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR | |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST | |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY | |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE | |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL | |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY, |
| - HDMI_IH_AHBDMAAUD_STAT0_ERROR = BIT(5), |
| - HDMI_IH_AHBDMAAUD_STAT0_LOST = BIT(4), |
| - HDMI_IH_AHBDMAAUD_STAT0_RETRY = BIT(3), |
| - HDMI_IH_AHBDMAAUD_STAT0_DONE = BIT(2), |
| - HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = BIT(1), |
| - HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0), |
| - HDMI_IH_AHBDMAAUD_STAT0_ALL = |
| - HDMI_IH_AHBDMAAUD_STAT0_ERROR | |
| - HDMI_IH_AHBDMAAUD_STAT0_LOST | |
| - HDMI_IH_AHBDMAAUD_STAT0_RETRY | |
| - HDMI_IH_AHBDMAAUD_STAT0_DONE | |
| - HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL | |
| - HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY, |
| - HDMI_AHB_DMA_CONF0_INCR16 = 2 << 1, |
| - HDMI_AHB_DMA_CONF0_INCR8 = 1 << 1, |
| - HDMI_AHB_DMA_CONF0_INCR4 = 0, |
| - HDMI_AHB_DMA_CONF0_BURST_MODE = BIT(0), |
| - HDMI_AHB_DMA_MASK_DONE = BIT(7), |
| - |
| - HDMI_REVISION_ID = 0x0001, |
| - HDMI_IH_AHBDMAAUD_STAT0 = 0x0109, |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189, |
| - HDMI_FC_AUDICONF2 = 0x1027, |
| - HDMI_FC_AUDSCONF = 0x1063, |
| - HDMI_FC_AUDSCONF_LAYOUT1 = 1 << 0, |
| - HDMI_FC_AUDSCONF_LAYOUT0 = 0 << 0, |
| - HDMI_AHB_DMA_CONF0 = 0x3600, |
| - HDMI_AHB_DMA_START = 0x3601, |
| - HDMI_AHB_DMA_STOP = 0x3602, |
| - HDMI_AHB_DMA_THRSLD = 0x3603, |
| - HDMI_AHB_DMA_STRADDR0 = 0x3604, |
| - HDMI_AHB_DMA_STPADDR0 = 0x3608, |
| - HDMI_AHB_DMA_MASK = 0x3614, |
| - HDMI_AHB_DMA_POL = 0x3615, |
| - HDMI_AHB_DMA_CONF1 = 0x3616, |
| - HDMI_AHB_DMA_BUFFPOL = 0x361a, |
| -}; |
| - |
| -struct dw_hdmi_channel_conf { |
| - u8 conf1; |
| - u8 ca; |
| -}; |
| - |
| -/* |
| - * The default mapping of ALSA channels to HDMI channels and speaker |
| - * allocation bits. Note that we can't do channel remapping here - |
| - * channels must be in the same order. |
| - * |
| - * Mappings for alsa-lib pcm/surround*.conf files: |
| - * |
| - * Front Sur4.0 Sur4.1 Sur5.0 Sur5.1 Sur7.1 |
| - * Channels 2 4 6 6 6 8 |
| - * |
| - * Our mapping from ALSA channel to CEA686D speaker name and HDMI channel: |
| - * |
| - * Number of ALSA channels |
| - * ALSA Channel 2 3 4 5 6 7 8 |
| - * 0 FL:0 = = = = = = |
| - * 1 FR:1 = = = = = = |
| - * 2 FC:3 RL:4 LFE:2 = = = |
| - * 3 RR:5 RL:4 FC:3 = = |
| - * 4 RR:5 RL:4 = = |
| - * 5 RR:5 = = |
| - * 6 RC:6 = |
| - * 7 RLC/FRC RLC/FRC |
| - */ |
| -static struct dw_hdmi_channel_conf default_hdmi_channel_config[7] = { |
| - { 0x03, 0x00 }, /* FL,FR */ |
| - { 0x0b, 0x02 }, /* FL,FR,FC */ |
| - { 0x33, 0x08 }, /* FL,FR,RL,RR */ |
| - { 0x37, 0x09 }, /* FL,FR,LFE,RL,RR */ |
| - { 0x3f, 0x0b }, /* FL,FR,LFE,FC,RL,RR */ |
| - { 0x7f, 0x0f }, /* FL,FR,LFE,FC,RL,RR,RC */ |
| - { 0xff, 0x13 }, /* FL,FR,LFE,FC,RL,RR,[FR]RC,[FR]LC */ |
| -}; |
| - |
| -struct snd_dw_hdmi { |
| - struct snd_card *card; |
| - struct snd_pcm *pcm; |
| - spinlock_t lock; |
| - struct dw_hdmi_audio_data data; |
| - struct snd_pcm_substream *substream; |
| - void (*reformat)(struct snd_dw_hdmi *, size_t, size_t); |
| - void *buf_src; |
| - void *buf_dst; |
| - dma_addr_t buf_addr; |
| - unsigned buf_offset; |
| - unsigned buf_period; |
| - unsigned buf_size; |
| - unsigned channels; |
| - u8 revision; |
| - u8 iec_offset; |
| - u8 cs[192][8]; |
| -}; |
| - |
| -static void dw_hdmi_writel(u32 val, void __iomem *ptr) |
| -{ |
| - writeb_relaxed(val, ptr); |
| - writeb_relaxed(val >> 8, ptr + 1); |
| - writeb_relaxed(val >> 16, ptr + 2); |
| - writeb_relaxed(val >> 24, ptr + 3); |
| -} |
| - |
| -/* |
| - * Convert to hardware format: The userspace buffer contains IEC958 samples, |
| - * with the PCUV bits in bits 31..28 and audio samples in bits 27..4. We |
| - * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio |
| - * samples in 23..0. |
| - * |
| - * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd |
| - * |
| - * Ideally, we could do with having the data properly formatted in userspace. |
| - */ |
| -static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw, |
| - size_t offset, size_t bytes) |
| -{ |
| - u32 *src = dw->buf_src + offset; |
| - u32 *dst = dw->buf_dst + offset; |
| - u32 *end = dw->buf_src + offset + bytes; |
| - |
| - do { |
| - u32 b, sample = *src++; |
| - |
| - b = (sample & 8) << (28 - 3); |
| - |
| - sample >>= 4; |
| - |
| - *dst++ = sample | b; |
| - } while (src < end); |
| -} |
| - |
| -static u32 parity(u32 sample) |
| -{ |
| - sample ^= sample >> 16; |
| - sample ^= sample >> 8; |
| - sample ^= sample >> 4; |
| - sample ^= sample >> 2; |
| - sample ^= sample >> 1; |
| - return (sample & 1) << 27; |
| -} |
| - |
| -static void dw_hdmi_reformat_s24(struct snd_dw_hdmi *dw, |
| - size_t offset, size_t bytes) |
| -{ |
| - u32 *src = dw->buf_src + offset; |
| - u32 *dst = dw->buf_dst + offset; |
| - u32 *end = dw->buf_src + offset + bytes; |
| - |
| - do { |
| - unsigned i; |
| - u8 *cs; |
| - |
| - cs = dw->cs[dw->iec_offset++]; |
| - if (dw->iec_offset >= 192) |
| - dw->iec_offset = 0; |
| - |
| - i = dw->channels; |
| - do { |
| - u32 sample = *src++; |
| - |
| - sample &= ~0xff000000; |
| - sample |= *cs++ << 24; |
| - sample |= parity(sample & ~0xf8000000); |
| - |
| - *dst++ = sample; |
| - } while (--i); |
| - } while (src < end); |
| -} |
| - |
| -static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw, |
| - struct snd_pcm_runtime *runtime) |
| -{ |
| - u8 cs[4]; |
| - unsigned ch, i, j; |
| - |
| - snd_pcm_create_iec958_consumer(runtime, cs, sizeof(cs)); |
| - |
| - memset(dw->cs, 0, sizeof(dw->cs)); |
| - |
| - for (ch = 0; ch < 8; ch++) { |
| - cs[2] &= ~IEC958_AES2_CON_CHANNEL; |
| - cs[2] |= (ch + 1) << 4; |
| - |
| - for (i = 0; i < ARRAY_SIZE(cs); i++) { |
| - unsigned c = cs[i]; |
| - |
| - for (j = 0; j < 8; j++, c >>= 1) |
| - dw->cs[i * 8 + j][ch] = (c & 1) << 2; |
| - } |
| - } |
| - dw->cs[0][0] |= BIT(4); |
| -} |
| - |
| -static void dw_hdmi_start_dma(struct snd_dw_hdmi *dw) |
| -{ |
| - void __iomem *base = dw->data.base; |
| - unsigned offset = dw->buf_offset; |
| - unsigned period = dw->buf_period; |
| - u32 start, stop; |
| - |
| - dw->reformat(dw, offset, period); |
| - |
| - /* Clear all irqs before enabling irqs and starting DMA */ |
| - writeb_relaxed(HDMI_IH_AHBDMAAUD_STAT0_ALL, |
| - base + HDMI_IH_AHBDMAAUD_STAT0); |
| - |
| - start = dw->buf_addr + offset; |
| - stop = start + period - 1; |
| - |
| - /* Setup the hardware start/stop addresses */ |
| - dw_hdmi_writel(start, base + HDMI_AHB_DMA_STRADDR0); |
| - dw_hdmi_writel(stop, base + HDMI_AHB_DMA_STPADDR0); |
| - |
| - writeb_relaxed((u8)~HDMI_AHB_DMA_MASK_DONE, base + HDMI_AHB_DMA_MASK); |
| - writeb(HDMI_AHB_DMA_START_START, base + HDMI_AHB_DMA_START); |
| - |
| - offset += period; |
| - if (offset >= dw->buf_size) |
| - offset = 0; |
| - dw->buf_offset = offset; |
| -} |
| - |
| -static void dw_hdmi_stop_dma(struct snd_dw_hdmi *dw) |
| -{ |
| - /* Disable interrupts before disabling DMA */ |
| - writeb_relaxed(~0, dw->data.base + HDMI_AHB_DMA_MASK); |
| - writeb_relaxed(HDMI_AHB_DMA_STOP_STOP, dw->data.base + HDMI_AHB_DMA_STOP); |
| -} |
| - |
| -static irqreturn_t snd_dw_hdmi_irq(int irq, void *data) |
| -{ |
| - struct snd_dw_hdmi *dw = data; |
| - struct snd_pcm_substream *substream; |
| - unsigned stat; |
| - |
| - stat = readb_relaxed(dw->data.base + HDMI_IH_AHBDMAAUD_STAT0); |
| - if (!stat) |
| - return IRQ_NONE; |
| - |
| - writeb_relaxed(stat, dw->data.base + HDMI_IH_AHBDMAAUD_STAT0); |
| - |
| - substream = dw->substream; |
| - if (stat & HDMI_IH_AHBDMAAUD_STAT0_DONE && substream) { |
| - snd_pcm_period_elapsed(substream); |
| - |
| - spin_lock(&dw->lock); |
| - if (dw->substream) |
| - dw_hdmi_start_dma(dw); |
| - spin_unlock(&dw->lock); |
| - } |
| - |
| - return IRQ_HANDLED; |
| -} |
| - |
| -static struct snd_pcm_hardware dw_hdmi_hw = { |
| - .info = SNDRV_PCM_INFO_INTERLEAVED | |
| - SNDRV_PCM_INFO_BLOCK_TRANSFER | |
| - SNDRV_PCM_INFO_MMAP | |
| - SNDRV_PCM_INFO_MMAP_VALID, |
| - .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | |
| - SNDRV_PCM_FMTBIT_S24_LE, |
| - .rates = SNDRV_PCM_RATE_32000 | |
| - SNDRV_PCM_RATE_44100 | |
| - SNDRV_PCM_RATE_48000 | |
| - SNDRV_PCM_RATE_88200 | |
| - SNDRV_PCM_RATE_96000 | |
| - SNDRV_PCM_RATE_176400 | |
| - SNDRV_PCM_RATE_192000, |
| - .channels_min = 2, |
| - .channels_max = 8, |
| - .buffer_bytes_max = 1024 * 1024, |
| - .period_bytes_min = 256, |
| - .period_bytes_max = 8192, /* ERR004323: must limit to 8k */ |
| - .periods_min = 2, |
| - .periods_max = 16, |
| - .fifo_size = 0, |
| -}; |
| - |
| -static int dw_hdmi_open(struct snd_pcm_substream *substream) |
| -{ |
| - struct snd_pcm_runtime *runtime = substream->runtime; |
| - struct snd_dw_hdmi *dw = substream->private_data; |
| - void __iomem *base = dw->data.base; |
| - int ret; |
| - |
| - runtime->hw = dw_hdmi_hw; |
| - |
| - ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld); |
| - if (ret < 0) |
| - return ret; |
| - |
| - ret = snd_pcm_limit_hw_rates(runtime); |
| - if (ret < 0) |
| - return ret; |
| - |
| - ret = snd_pcm_hw_constraint_integer(runtime, |
| - SNDRV_PCM_HW_PARAM_PERIODS); |
| - if (ret < 0) |
| - return ret; |
| - |
| - /* Limit the buffer size to the size of the preallocated buffer */ |
| - ret = snd_pcm_hw_constraint_minmax(runtime, |
| - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, |
| - 0, substream->dma_buffer.bytes); |
| - if (ret < 0) |
| - return ret; |
| - |
| - /* Clear FIFO */ |
| - writeb_relaxed(HDMI_AHB_DMA_CONF0_SW_FIFO_RST, |
| - base + HDMI_AHB_DMA_CONF0); |
| - |
| - /* Configure interrupt polarities */ |
| - writeb_relaxed(~0, base + HDMI_AHB_DMA_POL); |
| - writeb_relaxed(~0, base + HDMI_AHB_DMA_BUFFPOL); |
| - |
| - /* Keep interrupts masked, and clear any pending */ |
| - writeb_relaxed(~0, base + HDMI_AHB_DMA_MASK); |
| - writeb_relaxed(~0, base + HDMI_IH_AHBDMAAUD_STAT0); |
| - |
| - ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED, |
| - "dw-hdmi-audio", dw); |
| - if (ret) |
| - return ret; |
| - |
| - /* Un-mute done interrupt */ |
| - writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL & |
| - ~HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE, |
| - base + HDMI_IH_MUTE_AHBDMAAUD_STAT0); |
| - |
| - return 0; |
| -} |
| - |
| -static int dw_hdmi_close(struct snd_pcm_substream *substream) |
| -{ |
| - struct snd_dw_hdmi *dw = substream->private_data; |
| - |
| - /* Mute all interrupts */ |
| - writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL, |
| - dw->data.base + HDMI_IH_MUTE_AHBDMAAUD_STAT0); |
| - |
| - free_irq(dw->data.irq, dw); |
| - |
| - return 0; |
| -} |
| - |
| -static int dw_hdmi_hw_free(struct snd_pcm_substream *substream) |
| -{ |
| - return snd_pcm_lib_free_vmalloc_buffer(substream); |
| -} |
| - |
| -static int dw_hdmi_hw_params(struct snd_pcm_substream *substream, |
| - struct snd_pcm_hw_params *params) |
| -{ |
| - /* Allocate the PCM runtime buffer, which is exposed to userspace. */ |
| - return snd_pcm_lib_alloc_vmalloc_buffer(substream, |
| - params_buffer_bytes(params)); |
| -} |
| - |
| -static int dw_hdmi_prepare(struct snd_pcm_substream *substream) |
| -{ |
| - struct snd_pcm_runtime *runtime = substream->runtime; |
| - struct snd_dw_hdmi *dw = substream->private_data; |
| - u8 threshold, conf0, conf1, layout, ca; |
| - |
| - /* Setup as per 3.0.5 FSL 4.1.0 BSP */ |
| - switch (dw->revision) { |
| - case 0x0a: |
| - conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE | |
| - HDMI_AHB_DMA_CONF0_INCR4; |
| - if (runtime->channels == 2) |
| - threshold = 126; |
| - else |
| - threshold = 124; |
| - break; |
| - case 0x1a: |
| - conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE | |
| - HDMI_AHB_DMA_CONF0_INCR8; |
| - threshold = 128; |
| - break; |
| - default: |
| - /* NOTREACHED */ |
| - return -EINVAL; |
| - } |
| - |
| - dw_hdmi_set_sample_rate(dw->data.hdmi, runtime->rate); |
| - |
| - /* Minimum number of bytes in the fifo. */ |
| - runtime->hw.fifo_size = threshold * 32; |
| - |
| - conf0 |= HDMI_AHB_DMA_CONF0_EN_HLOCK; |
| - conf1 = default_hdmi_channel_config[runtime->channels - 2].conf1; |
| - ca = default_hdmi_channel_config[runtime->channels - 2].ca; |
| - |
| - /* |
| - * For >2 channel PCM audio, we need to select layout 1 |
| - * and set an appropriate channel map. |
| - */ |
| - if (runtime->channels > 2) |
| - layout = HDMI_FC_AUDSCONF_LAYOUT1; |
| - else |
| - layout = HDMI_FC_AUDSCONF_LAYOUT0; |
| - |
| - writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD); |
| - writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0); |
| - writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1); |
| - writeb_relaxed(layout, dw->data.base + HDMI_FC_AUDSCONF); |
| - writeb_relaxed(ca, dw->data.base + HDMI_FC_AUDICONF2); |
| - |
| - switch (runtime->format) { |
| - case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: |
| - dw->reformat = dw_hdmi_reformat_iec958; |
| - break; |
| - case SNDRV_PCM_FORMAT_S24_LE: |
| - dw_hdmi_create_cs(dw, runtime); |
| - dw->reformat = dw_hdmi_reformat_s24; |
| - break; |
| - } |
| - dw->iec_offset = 0; |
| - dw->channels = runtime->channels; |
| - dw->buf_src = runtime->dma_area; |
| - dw->buf_dst = substream->dma_buffer.area; |
| - dw->buf_addr = substream->dma_buffer.addr; |
| - dw->buf_period = snd_pcm_lib_period_bytes(substream); |
| - dw->buf_size = snd_pcm_lib_buffer_bytes(substream); |
| - |
| - return 0; |
| -} |
| - |
| -static int dw_hdmi_trigger(struct snd_pcm_substream *substream, int cmd) |
| -{ |
| - struct snd_dw_hdmi *dw = substream->private_data; |
| - unsigned long flags; |
| - int ret = 0; |
| - |
| - switch (cmd) { |
| - case SNDRV_PCM_TRIGGER_START: |
| - spin_lock_irqsave(&dw->lock, flags); |
| - dw->buf_offset = 0; |
| - dw->substream = substream; |
| - dw_hdmi_start_dma(dw); |
| - dw_hdmi_audio_enable(dw->data.hdmi); |
| - spin_unlock_irqrestore(&dw->lock, flags); |
| - substream->runtime->delay = substream->runtime->period_size; |
| - break; |
| - |
| - case SNDRV_PCM_TRIGGER_STOP: |
| - spin_lock_irqsave(&dw->lock, flags); |
| - dw->substream = NULL; |
| - dw_hdmi_stop_dma(dw); |
| - dw_hdmi_audio_disable(dw->data.hdmi); |
| - spin_unlock_irqrestore(&dw->lock, flags); |
| - break; |
| - |
| - default: |
| - ret = -EINVAL; |
| - break; |
| - } |
| - |
| - return ret; |
| -} |
| - |
| -static snd_pcm_uframes_t dw_hdmi_pointer(struct snd_pcm_substream *substream) |
| -{ |
| - struct snd_pcm_runtime *runtime = substream->runtime; |
| - struct snd_dw_hdmi *dw = substream->private_data; |
| - |
| - /* |
| - * We are unable to report the exact hardware position as |
| - * reading the 32-bit DMA position using 8-bit reads is racy. |
| - */ |
| - return bytes_to_frames(runtime, dw->buf_offset); |
| -} |
| - |
| -static struct snd_pcm_ops snd_dw_hdmi_ops = { |
| - .open = dw_hdmi_open, |
| - .close = dw_hdmi_close, |
| - .ioctl = snd_pcm_lib_ioctl, |
| - .hw_params = dw_hdmi_hw_params, |
| - .hw_free = dw_hdmi_hw_free, |
| - .prepare = dw_hdmi_prepare, |
| - .trigger = dw_hdmi_trigger, |
| - .pointer = dw_hdmi_pointer, |
| - .page = snd_pcm_lib_get_vmalloc_page, |
| -}; |
| - |
| -static int snd_dw_hdmi_probe(struct platform_device *pdev) |
| -{ |
| - const struct dw_hdmi_audio_data *data = pdev->dev.platform_data; |
| - struct device *dev = pdev->dev.parent; |
| - struct snd_dw_hdmi *dw; |
| - struct snd_card *card; |
| - struct snd_pcm *pcm; |
| - unsigned revision; |
| - int ret; |
| - |
| - writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL, |
| - data->base + HDMI_IH_MUTE_AHBDMAAUD_STAT0); |
| - revision = readb_relaxed(data->base + HDMI_REVISION_ID); |
| - if (revision != 0x0a && revision != 0x1a) { |
| - dev_err(dev, "dw-hdmi-audio: unknown revision 0x%02x\n", |
| - revision); |
| - return -ENXIO; |
| - } |
| - |
| - ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
| - THIS_MODULE, sizeof(struct snd_dw_hdmi), &card); |
| - if (ret < 0) |
| - return ret; |
| - |
| - strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); |
| - strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname)); |
| - snprintf(card->longname, sizeof(card->longname), |
| - "%s rev 0x%02x, irq %d", card->shortname, revision, |
| - data->irq); |
| - |
| - dw = card->private_data; |
| - dw->card = card; |
| - dw->data = *data; |
| - dw->revision = revision; |
| - |
| - spin_lock_init(&dw->lock); |
| - |
| - ret = snd_pcm_new(card, "DW HDMI", 0, 1, 0, &pcm); |
| - if (ret < 0) |
| - goto err; |
| - |
| - dw->pcm = pcm; |
| - pcm->private_data = dw; |
| - strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); |
| - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops); |
| - |
| - /* |
| - * To support 8-channel 96kHz audio reliably, we need 512k |
| - * to satisfy alsa with our restricted period (ERR004323). |
| - */ |
| - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
| - dev, 128 * 1024, 1024 * 1024); |
| - |
| - ret = snd_card_register(card); |
| - if (ret < 0) |
| - goto err; |
| - |
| - platform_set_drvdata(pdev, dw); |
| - |
| - return 0; |
| - |
| -err: |
| - snd_card_free(card); |
| - return ret; |
| -} |
| - |
| -static int snd_dw_hdmi_remove(struct platform_device *pdev) |
| -{ |
| - struct snd_dw_hdmi *dw = platform_get_drvdata(pdev); |
| - |
| - snd_card_free(dw->card); |
| - |
| - return 0; |
| -} |
| - |
| -#if defined(CONFIG_PM_SLEEP) && defined(IS_NOT_BROKEN) |
| -/* |
| - * This code is fine, but requires implementation in the dw_hdmi_trigger() |
| - * method which is currently missing as I have no way to test this. |
| - */ |
| -static int snd_dw_hdmi_suspend(struct device *dev) |
| -{ |
| - struct snd_dw_hdmi *dw = dev_get_drvdata(dev); |
| - |
| - snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold); |
| - snd_pcm_suspend_all(dw->pcm); |
| - |
| - return 0; |
| -} |
| - |
| -static int snd_dw_hdmi_resume(struct device *dev) |
| -{ |
| - struct snd_dw_hdmi *dw = dev_get_drvdata(dev); |
| - |
| - snd_power_change_state(dw->card, SNDRV_CTL_POWER_D0); |
| - |
| - return 0; |
| -} |
| - |
| -static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend, |
| - snd_dw_hdmi_resume); |
| -#define PM_OPS &snd_dw_hdmi_pm |
| -#else |
| -#define PM_OPS NULL |
| -#endif |
| - |
| -static struct platform_driver snd_dw_hdmi_driver = { |
| - .probe = snd_dw_hdmi_probe, |
| - .remove = snd_dw_hdmi_remove, |
| - .driver = { |
| - .name = DRIVER_NAME, |
| - .pm = PM_OPS, |
| - }, |
| -}; |
| - |
| -module_platform_driver(snd_dw_hdmi_driver); |
| - |
| -MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>"); |
| -MODULE_DESCRIPTION("Synopsis Designware HDMI AHB ALSA interface"); |
| -MODULE_LICENSE("GPL v2"); |
| -MODULE_ALIAS("platform:" DRIVER_NAME); |
| --- a/drivers/gpu/drm/bridge/dw-hdmi-audio.h |
| +++ /dev/null |
| @@ -1,21 +0,0 @@ |
| -#ifndef DW_HDMI_AUDIO_H |
| -#define DW_HDMI_AUDIO_H |
| - |
| -struct dw_hdmi; |
| - |
| -struct dw_hdmi_audio_data { |
| - phys_addr_t phys; |
| - void __iomem *base; |
| - int irq; |
| - struct dw_hdmi *hdmi; |
| - u8 *eld; |
| -}; |
| - |
| -struct dw_hdmi_i2s_audio_data { |
| - struct dw_hdmi *hdmi; |
| - |
| - void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); |
| - u8 (*read)(struct dw_hdmi *hdmi, int offset); |
| -}; |
| - |
| -#endif |
| --- a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c |
| +++ /dev/null |
| @@ -1,141 +0,0 @@ |
| -/* |
| - * dw-hdmi-i2s-audio.c |
| - * |
| - * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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. |
| - */ |
| -#include <drm/bridge/dw_hdmi.h> |
| - |
| -#include <sound/hdmi-codec.h> |
| - |
| -#include "dw-hdmi.h" |
| -#include "dw-hdmi-audio.h" |
| - |
| -#define DRIVER_NAME "dw-hdmi-i2s-audio" |
| - |
| -static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio, |
| - u8 val, int offset) |
| -{ |
| - struct dw_hdmi *hdmi = audio->hdmi; |
| - |
| - audio->write(hdmi, val, offset); |
| -} |
| - |
| -static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset) |
| -{ |
| - struct dw_hdmi *hdmi = audio->hdmi; |
| - |
| - return audio->read(hdmi, offset); |
| -} |
| - |
| -static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, |
| - struct hdmi_codec_daifmt *fmt, |
| - struct hdmi_codec_params *hparms) |
| -{ |
| - struct dw_hdmi_i2s_audio_data *audio = data; |
| - struct dw_hdmi *hdmi = audio->hdmi; |
| - u8 conf0 = 0; |
| - u8 conf1 = 0; |
| - u8 inputclkfs = 0; |
| - |
| - /* it cares I2S only */ |
| - if ((fmt->fmt != HDMI_I2S) || |
| - (fmt->bit_clk_master | fmt->frame_clk_master)) { |
| - dev_err(dev, "unsupported format/settings\n"); |
| - return -EINVAL; |
| - } |
| - |
| - inputclkfs = HDMI_AUD_INPUTCLKFS_64FS; |
| - conf0 = HDMI_AUD_CONF0_I2S_ALL_ENABLE; |
| - |
| - switch (hparms->sample_width) { |
| - case 16: |
| - conf1 = HDMI_AUD_CONF1_WIDTH_16; |
| - break; |
| - case 24: |
| - case 32: |
| - conf1 = HDMI_AUD_CONF1_WIDTH_24; |
| - break; |
| - } |
| - |
| - dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate); |
| - |
| - hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS); |
| - hdmi_write(audio, conf0, HDMI_AUD_CONF0); |
| - hdmi_write(audio, conf1, HDMI_AUD_CONF1); |
| - |
| - dw_hdmi_audio_enable(hdmi); |
| - |
| - return 0; |
| -} |
| - |
| -static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) |
| -{ |
| - struct dw_hdmi_i2s_audio_data *audio = data; |
| - struct dw_hdmi *hdmi = audio->hdmi; |
| - |
| - dw_hdmi_audio_disable(hdmi); |
| - |
| - hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); |
| -} |
| - |
| -static struct hdmi_codec_ops dw_hdmi_i2s_ops = { |
| - .hw_params = dw_hdmi_i2s_hw_params, |
| - .audio_shutdown = dw_hdmi_i2s_audio_shutdown, |
| -}; |
| - |
| -static int snd_dw_hdmi_probe(struct platform_device *pdev) |
| -{ |
| - struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data; |
| - struct platform_device_info pdevinfo; |
| - struct hdmi_codec_pdata pdata; |
| - struct platform_device *platform; |
| - |
| - pdata.ops = &dw_hdmi_i2s_ops; |
| - pdata.i2s = 1; |
| - pdata.max_i2s_channels = 6; |
| - pdata.data = audio; |
| - |
| - memset(&pdevinfo, 0, sizeof(pdevinfo)); |
| - pdevinfo.parent = pdev->dev.parent; |
| - pdevinfo.id = PLATFORM_DEVID_AUTO; |
| - pdevinfo.name = HDMI_CODEC_DRV_NAME; |
| - pdevinfo.data = &pdata; |
| - pdevinfo.size_data = sizeof(pdata); |
| - pdevinfo.dma_mask = DMA_BIT_MASK(32); |
| - |
| - platform = platform_device_register_full(&pdevinfo); |
| - if (IS_ERR(platform)) |
| - return PTR_ERR(platform); |
| - |
| - dev_set_drvdata(&pdev->dev, platform); |
| - |
| - return 0; |
| -} |
| - |
| -static int snd_dw_hdmi_remove(struct platform_device *pdev) |
| -{ |
| - struct platform_device *platform = dev_get_drvdata(&pdev->dev); |
| - |
| - platform_device_unregister(platform); |
| - |
| - return 0; |
| -} |
| - |
| -static struct platform_driver snd_dw_hdmi_driver = { |
| - .probe = snd_dw_hdmi_probe, |
| - .remove = snd_dw_hdmi_remove, |
| - .driver = { |
| - .name = DRIVER_NAME, |
| - .owner = THIS_MODULE, |
| - }, |
| -}; |
| -module_platform_driver(snd_dw_hdmi_driver); |
| - |
| -MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); |
| -MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface"); |
| -MODULE_LICENSE("GPL v2"); |
| -MODULE_ALIAS("platform:" DRIVER_NAME); |
| --- a/drivers/gpu/drm/bridge/dw-hdmi.c |
| +++ /dev/null |
| @@ -1,2314 +0,0 @@ |
| -/* |
| - * DesignWare High-Definition Multimedia Interface (HDMI) driver |
| - * |
| - * Copyright (C) 2013-2015 Mentor Graphics Inc. |
| - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. |
| - * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> |
| - * |
| - * This program is free software; you can redistribute it and/or modify |
| - * it under the terms of the GNU General Public License as published by |
| - * the Free Software Foundation; either version 2 of the License, or |
| - * (at your option) any later version. |
| - * |
| - */ |
| -#include <linux/module.h> |
| -#include <linux/irq.h> |
| -#include <linux/delay.h> |
| -#include <linux/err.h> |
| -#include <linux/clk.h> |
| -#include <linux/hdmi.h> |
| -#include <linux/mutex.h> |
| -#include <linux/of_device.h> |
| -#include <linux/regmap.h> |
| -#include <linux/spinlock.h> |
| - |
| -#include <drm/drm_of.h> |
| -#include <drm/drmP.h> |
| -#include <drm/drm_atomic_helper.h> |
| -#include <drm/drm_crtc_helper.h> |
| -#include <drm/drm_edid.h> |
| -#include <drm/drm_encoder_slave.h> |
| -#include <drm/bridge/dw_hdmi.h> |
| - |
| -#include "dw-hdmi.h" |
| -#include "dw-hdmi-audio.h" |
| - |
| -#define HDMI_EDID_LEN 512 |
| - |
| -#define RGB 0 |
| -#define YCBCR444 1 |
| -#define YCBCR422_16BITS 2 |
| -#define YCBCR422_8BITS 3 |
| -#define XVYCC444 4 |
| - |
| -enum hdmi_datamap { |
| - RGB444_8B = 0x01, |
| - RGB444_10B = 0x03, |
| - RGB444_12B = 0x05, |
| - RGB444_16B = 0x07, |
| - YCbCr444_8B = 0x09, |
| - YCbCr444_10B = 0x0B, |
| - YCbCr444_12B = 0x0D, |
| - YCbCr444_16B = 0x0F, |
| - YCbCr422_8B = 0x16, |
| - YCbCr422_10B = 0x14, |
| - YCbCr422_12B = 0x12, |
| -}; |
| - |
| -static const u16 csc_coeff_default[3][4] = { |
| - { 0x2000, 0x0000, 0x0000, 0x0000 }, |
| - { 0x0000, 0x2000, 0x0000, 0x0000 }, |
| - { 0x0000, 0x0000, 0x2000, 0x0000 } |
| -}; |
| - |
| -static const u16 csc_coeff_rgb_out_eitu601[3][4] = { |
| - { 0x2000, 0x6926, 0x74fd, 0x010e }, |
| - { 0x2000, 0x2cdd, 0x0000, 0x7e9a }, |
| - { 0x2000, 0x0000, 0x38b4, 0x7e3b } |
| -}; |
| - |
| -static const u16 csc_coeff_rgb_out_eitu709[3][4] = { |
| - { 0x2000, 0x7106, 0x7a02, 0x00a7 }, |
| - { 0x2000, 0x3264, 0x0000, 0x7e6d }, |
| - { 0x2000, 0x0000, 0x3b61, 0x7e25 } |
| -}; |
| - |
| -static const u16 csc_coeff_rgb_in_eitu601[3][4] = { |
| - { 0x2591, 0x1322, 0x074b, 0x0000 }, |
| - { 0x6535, 0x2000, 0x7acc, 0x0200 }, |
| - { 0x6acd, 0x7534, 0x2000, 0x0200 } |
| -}; |
| - |
| -static const u16 csc_coeff_rgb_in_eitu709[3][4] = { |
| - { 0x2dc5, 0x0d9b, 0x049e, 0x0000 }, |
| - { 0x62f0, 0x2000, 0x7d11, 0x0200 }, |
| - { 0x6756, 0x78ab, 0x2000, 0x0200 } |
| -}; |
| - |
| -struct hdmi_vmode { |
| - bool mdataenablepolarity; |
| - |
| - unsigned int mpixelclock; |
| - unsigned int mpixelrepetitioninput; |
| - unsigned int mpixelrepetitionoutput; |
| -}; |
| - |
| -struct hdmi_data_info { |
| - unsigned int enc_in_format; |
| - unsigned int enc_out_format; |
| - unsigned int enc_color_depth; |
| - unsigned int colorimetry; |
| - unsigned int pix_repet_factor; |
| - unsigned int hdcp_enable; |
| - struct hdmi_vmode video_mode; |
| -}; |
| - |
| -struct dw_hdmi_i2c { |
| - struct i2c_adapter adap; |
| - |
| - struct mutex lock; /* used to serialize data transfers */ |
| - struct completion cmp; |
| - u8 stat; |
| - |
| - u8 slave_reg; |
| - bool is_regaddr; |
| -}; |
| - |
| -struct dw_hdmi_phy_data { |
| - enum dw_hdmi_phy_type type; |
| - const char *name; |
| - unsigned int gen; |
| - bool has_svsret; |
| - int (*configure)(struct dw_hdmi *hdmi, |
| - const struct dw_hdmi_plat_data *pdata, |
| - unsigned long mpixelclock); |
| -}; |
| - |
| -struct dw_hdmi { |
| - struct drm_connector connector; |
| - struct drm_bridge bridge; |
| - |
| - unsigned int version; |
| - |
| - struct platform_device *audio; |
| - struct device *dev; |
| - struct clk *isfr_clk; |
| - struct clk *iahb_clk; |
| - struct dw_hdmi_i2c *i2c; |
| - |
| - struct hdmi_data_info hdmi_data; |
| - const struct dw_hdmi_plat_data *plat_data; |
| - |
| - int vic; |
| - |
| - u8 edid[HDMI_EDID_LEN]; |
| - bool cable_plugin; |
| - |
| - struct { |
| - const struct dw_hdmi_phy_ops *ops; |
| - const char *name; |
| - void *data; |
| - bool enabled; |
| - } phy; |
| - |
| - struct drm_display_mode previous_mode; |
| - |
| - struct i2c_adapter *ddc; |
| - void __iomem *regs; |
| - bool sink_is_hdmi; |
| - bool sink_has_audio; |
| - |
| - struct mutex mutex; /* for state below and previous_mode */ |
| - enum drm_connector_force force; /* mutex-protected force state */ |
| - bool disabled; /* DRM has disabled our bridge */ |
| - bool bridge_is_on; /* indicates the bridge is on */ |
| - bool rxsense; /* rxsense state */ |
| - u8 phy_mask; /* desired phy int mask settings */ |
| - |
| - spinlock_t audio_lock; |
| - struct mutex audio_mutex; |
| - unsigned int sample_rate; |
| - unsigned int audio_cts; |
| - unsigned int audio_n; |
| - bool audio_enable; |
| - |
| - unsigned int reg_shift; |
| - struct regmap *regm; |
| -}; |
| - |
| -#define HDMI_IH_PHY_STAT0_RX_SENSE \ |
| - (HDMI_IH_PHY_STAT0_RX_SENSE0 | HDMI_IH_PHY_STAT0_RX_SENSE1 | \ |
| - HDMI_IH_PHY_STAT0_RX_SENSE2 | HDMI_IH_PHY_STAT0_RX_SENSE3) |
| - |
| -#define HDMI_PHY_RX_SENSE \ |
| - (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \ |
| - HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3) |
| - |
| -static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) |
| -{ |
| - regmap_write(hdmi->regm, offset << hdmi->reg_shift, val); |
| -} |
| - |
| -static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset) |
| -{ |
| - unsigned int val = 0; |
| - |
| - regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val); |
| - |
| - return val; |
| -} |
| - |
| -static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg) |
| -{ |
| - regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data); |
| -} |
| - |
| -static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, |
| - u8 shift, u8 mask) |
| -{ |
| - hdmi_modb(hdmi, data << shift, mask, reg); |
| -} |
| - |
| -static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi) |
| -{ |
| - /* Software reset */ |
| - hdmi_writeb(hdmi, 0x00, HDMI_I2CM_SOFTRSTZ); |
| - |
| - /* Set Standard Mode speed (determined to be 100KHz on iMX6) */ |
| - hdmi_writeb(hdmi, 0x00, HDMI_I2CM_DIV); |
| - |
| - /* Set done, not acknowledged and arbitration interrupt polarities */ |
| - hdmi_writeb(hdmi, HDMI_I2CM_INT_DONE_POL, HDMI_I2CM_INT); |
| - hdmi_writeb(hdmi, HDMI_I2CM_CTLINT_NAC_POL | HDMI_I2CM_CTLINT_ARB_POL, |
| - HDMI_I2CM_CTLINT); |
| - |
| - /* Clear DONE and ERROR interrupts */ |
| - hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, |
| - HDMI_IH_I2CM_STAT0); |
| - |
| - /* Mute DONE and ERROR interrupts */ |
| - hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, |
| - HDMI_IH_MUTE_I2CM_STAT0); |
| -} |
| - |
| -static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi, |
| - unsigned char *buf, unsigned int length) |
| -{ |
| - struct dw_hdmi_i2c *i2c = hdmi->i2c; |
| - int stat; |
| - |
| - if (!i2c->is_regaddr) { |
| - dev_dbg(hdmi->dev, "set read register address to 0\n"); |
| - i2c->slave_reg = 0x00; |
| - i2c->is_regaddr = true; |
| - } |
| - |
| - while (length--) { |
| - reinit_completion(&i2c->cmp); |
| - |
| - hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS); |
| - hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ, |
| - HDMI_I2CM_OPERATION); |
| - |
| - stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); |
| - if (!stat) |
| - return -EAGAIN; |
| - |
| - /* Check for error condition on the bus */ |
| - if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) |
| - return -EIO; |
| - |
| - *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI); |
| - } |
| - |
| - return 0; |
| -} |
| - |
| -static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi, |
| - unsigned char *buf, unsigned int length) |
| -{ |
| - struct dw_hdmi_i2c *i2c = hdmi->i2c; |
| - int stat; |
| - |
| - if (!i2c->is_regaddr) { |
| - /* Use the first write byte as register address */ |
| - i2c->slave_reg = buf[0]; |
| - length--; |
| - buf++; |
| - i2c->is_regaddr = true; |
| - } |
| - |
| - while (length--) { |
| - reinit_completion(&i2c->cmp); |
| - |
| - hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO); |
| - hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS); |
| - hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE, |
| - HDMI_I2CM_OPERATION); |
| - |
| - stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); |
| - if (!stat) |
| - return -EAGAIN; |
| - |
| - /* Check for error condition on the bus */ |
| - if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) |
| - return -EIO; |
| - } |
| - |
| - return 0; |
| -} |
| - |
| -static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, |
| - struct i2c_msg *msgs, int num) |
| -{ |
| - struct dw_hdmi *hdmi = i2c_get_adapdata(adap); |
| - struct dw_hdmi_i2c *i2c = hdmi->i2c; |
| - u8 addr = msgs[0].addr; |
| - int i, ret = 0; |
| - |
| - dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr); |
| - |
| - for (i = 0; i < num; i++) { |
| - if (msgs[i].addr != addr) { |
| - dev_warn(hdmi->dev, |
| - "unsupported transfer, changed slave address\n"); |
| - return -EOPNOTSUPP; |
| - } |
| - |
| - if (msgs[i].len == 0) { |
| - dev_dbg(hdmi->dev, |
| - "unsupported transfer %d/%d, no data\n", |
| - i + 1, num); |
| - return -EOPNOTSUPP; |
| - } |
| - } |
| - |
| - mutex_lock(&i2c->lock); |
| - |
| - /* Unmute DONE and ERROR interrupts */ |
| - hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0); |
| - |
| - /* Set slave device address taken from the first I2C message */ |
| - hdmi_writeb(hdmi, addr, HDMI_I2CM_SLAVE); |
| - |
| - /* Set slave device register address on transfer */ |
| - i2c->is_regaddr = false; |
| - |
| - for (i = 0; i < num; i++) { |
| - dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n", |
| - i + 1, num, msgs[i].len, msgs[i].flags); |
| - |
| - if (msgs[i].flags & I2C_M_RD) |
| - ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len); |
| - else |
| - ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len); |
| - |
| - if (ret < 0) |
| - break; |
| - } |
| - |
| - if (!ret) |
| - ret = num; |
| - |
| - /* Mute DONE and ERROR interrupts */ |
| - hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, |
| - HDMI_IH_MUTE_I2CM_STAT0); |
| - |
| - mutex_unlock(&i2c->lock); |
| - |
| - return ret; |
| -} |
| - |
| -static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter) |
| -{ |
| - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
| -} |
| - |
| -static const struct i2c_algorithm dw_hdmi_algorithm = { |
| - .master_xfer = dw_hdmi_i2c_xfer, |
| - .functionality = dw_hdmi_i2c_func, |
| -}; |
| - |
| -static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi) |
| -{ |
| - struct i2c_adapter *adap; |
| - struct dw_hdmi_i2c *i2c; |
| - int ret; |
| - |
| - i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL); |
| - if (!i2c) |
| - return ERR_PTR(-ENOMEM); |
| - |
| - mutex_init(&i2c->lock); |
| - init_completion(&i2c->cmp); |
| - |
| - adap = &i2c->adap; |
| - adap->class = I2C_CLASS_DDC; |
| - adap->owner = THIS_MODULE; |
| - adap->dev.parent = hdmi->dev; |
| - adap->algo = &dw_hdmi_algorithm; |
| - strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name)); |
| - i2c_set_adapdata(adap, hdmi); |
| - |
| - ret = i2c_add_adapter(adap); |
| - if (ret) { |
| - dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name); |
| - devm_kfree(hdmi->dev, i2c); |
| - return ERR_PTR(ret); |
| - } |
| - |
| - hdmi->i2c = i2c; |
| - |
| - dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); |
| - |
| - return adap; |
| -} |
| - |
| -static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, |
| - unsigned int n) |
| -{ |
| - /* Must be set/cleared first */ |
| - hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); |
| - |
| - /* nshift factor = 0 */ |
| - hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); |
| - |
| - hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | |
| - HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); |
| - hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); |
| - hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); |
| - |
| - hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3); |
| - hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2); |
| - hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1); |
| -} |
| - |
| -static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk) |
| -{ |
| - unsigned int n = (128 * freq) / 1000; |
| - unsigned int mult = 1; |
| - |
| - while (freq > 48000) { |
| - mult *= 2; |
| - freq /= 2; |
| - } |
| - |
| - switch (freq) { |
| - case 32000: |
| - if (pixel_clk == 25175000) |
| - n = 4576; |
| - else if (pixel_clk == 27027000) |
| - n = 4096; |
| - else if (pixel_clk == 74176000 || pixel_clk == 148352000) |
| - n = 11648; |
| - else |
| - n = 4096; |
| - n *= mult; |
| - break; |
| - |
| - case 44100: |
| - if (pixel_clk == 25175000) |
| - n = 7007; |
| - else if (pixel_clk == 74176000) |
| - n = 17836; |
| - else if (pixel_clk == 148352000) |
| - n = 8918; |
| - else |
| - n = 6272; |
| - n *= mult; |
| - break; |
| - |
| - case 48000: |
| - if (pixel_clk == 25175000) |
| - n = 6864; |
| - else if (pixel_clk == 27027000) |
| - n = 6144; |
| - else if (pixel_clk == 74176000) |
| - n = 11648; |
| - else if (pixel_clk == 148352000) |
| - n = 5824; |
| - else |
| - n = 6144; |
| - n *= mult; |
| - break; |
| - |
| - default: |
| - break; |
| - } |
| - |
| - return n; |
| -} |
| - |
| -static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, |
| - unsigned long pixel_clk, unsigned int sample_rate) |
| -{ |
| - unsigned long ftdms = pixel_clk; |
| - unsigned int n, cts; |
| - u64 tmp; |
| - |
| - n = hdmi_compute_n(sample_rate, pixel_clk); |
| - |
| - /* |
| - * Compute the CTS value from the N value. Note that CTS and N |
| - * can be up to 20 bits in total, so we need 64-bit math. Also |
| - * note that our TDMS clock is not fully accurate; it is accurate |
| - * to kHz. This can introduce an unnecessary remainder in the |
| - * calculation below, so we don't try to warn about that. |
| - */ |
| - tmp = (u64)ftdms * n; |
| - do_div(tmp, 128 * sample_rate); |
| - cts = tmp; |
| - |
| - dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n", |
| - __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000, |
| - n, cts); |
| - |
| - spin_lock_irq(&hdmi->audio_lock); |
| - hdmi->audio_n = n; |
| - hdmi->audio_cts = cts; |
| - hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0); |
| - spin_unlock_irq(&hdmi->audio_lock); |
| -} |
| - |
| -static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) |
| -{ |
| - mutex_lock(&hdmi->audio_mutex); |
| - hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate); |
| - mutex_unlock(&hdmi->audio_mutex); |
| -} |
| - |
| -static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) |
| -{ |
| - mutex_lock(&hdmi->audio_mutex); |
| - hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock, |
| - hdmi->sample_rate); |
| - mutex_unlock(&hdmi->audio_mutex); |
| -} |
| - |
| -void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) |
| -{ |
| - mutex_lock(&hdmi->audio_mutex); |
| - hdmi->sample_rate = rate; |
| - hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock, |
| - hdmi->sample_rate); |
| - mutex_unlock(&hdmi->audio_mutex); |
| -} |
| -EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); |
| - |
| -void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) |
| -{ |
| - unsigned long flags; |
| - |
| - spin_lock_irqsave(&hdmi->audio_lock, flags); |
| - hdmi->audio_enable = true; |
| - hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); |
| - spin_unlock_irqrestore(&hdmi->audio_lock, flags); |
| -} |
| -EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable); |
| - |
| -void dw_hdmi_audio_disable(struct dw_hdmi *hdmi) |
| -{ |
| - unsigned long flags; |
| - |
| - spin_lock_irqsave(&hdmi->audio_lock, flags); |
| - hdmi->audio_enable = false; |
| - hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); |
| - spin_unlock_irqrestore(&hdmi->audio_lock, flags); |
| -} |
| -EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable); |
| - |
| -/* |
| - * this submodule is responsible for the video data synchronization. |
| - * for example, for RGB 4:4:4 input, the data map is defined as |
| - * pin{47~40} <==> R[7:0] |
| - * pin{31~24} <==> G[7:0] |
| - * pin{15~8} <==> B[7:0] |
| - */ |
| -static void hdmi_video_sample(struct dw_hdmi *hdmi) |
| -{ |
| - int color_format = 0; |
| - u8 val; |
| - |
| - if (hdmi->hdmi_data.enc_in_format == RGB) { |
| - if (hdmi->hdmi_data.enc_color_depth == 8) |
| - color_format = 0x01; |
| - else if (hdmi->hdmi_data.enc_color_depth == 10) |
| - color_format = 0x03; |
| - else if (hdmi->hdmi_data.enc_color_depth == 12) |
| - color_format = 0x05; |
| - else if (hdmi->hdmi_data.enc_color_depth == 16) |
| - color_format = 0x07; |
| - else |
| - return; |
| - } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) { |
| - if (hdmi->hdmi_data.enc_color_depth == 8) |
| - color_format = 0x09; |
| - else if (hdmi->hdmi_data.enc_color_depth == 10) |
| - color_format = 0x0B; |
| - else if (hdmi->hdmi_data.enc_color_depth == 12) |
| - color_format = 0x0D; |
| - else if (hdmi->hdmi_data.enc_color_depth == 16) |
| - color_format = 0x0F; |
| - else |
| - return; |
| - } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) { |
| - if (hdmi->hdmi_data.enc_color_depth == 8) |
| - color_format = 0x16; |
| - else if (hdmi->hdmi_data.enc_color_depth == 10) |
| - color_format = 0x14; |
| - else if (hdmi->hdmi_data.enc_color_depth == 12) |
| - color_format = 0x12; |
| - else |
| - return; |
| - } |
| - |
| - val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE | |
| - ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) & |
| - HDMI_TX_INVID0_VIDEO_MAPPING_MASK); |
| - hdmi_writeb(hdmi, val, HDMI_TX_INVID0); |
| - |
| - /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */ |
| - val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE | |
| - HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE | |
| - HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE; |
| - hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING); |
| - hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0); |
| - hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1); |
| - hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0); |
| - hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1); |
| - hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0); |
| - hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1); |
| -} |
| - |
| -static int is_color_space_conversion(struct dw_hdmi *hdmi) |
| -{ |
| - return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format; |
| -} |
| - |
| -static int is_color_space_decimation(struct dw_hdmi *hdmi) |
| -{ |
| - if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS) |
| - return 0; |
| - if (hdmi->hdmi_data.enc_in_format == RGB || |
| - hdmi->hdmi_data.enc_in_format == YCBCR444) |
| - return 1; |
| - return 0; |
| -} |
| - |
| -static int is_color_space_interpolation(struct dw_hdmi *hdmi) |
| -{ |
| - if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS) |
| - return 0; |
| - if (hdmi->hdmi_data.enc_out_format == RGB || |
| - hdmi->hdmi_data.enc_out_format == YCBCR444) |
| - return 1; |
| - return 0; |
| -} |
| - |
| -static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) |
| -{ |
| - const u16 (*csc_coeff)[3][4] = &csc_coeff_default; |
| - unsigned i; |
| - u32 csc_scale = 1; |
| - |
| - if (is_color_space_conversion(hdmi)) { |
| - if (hdmi->hdmi_data.enc_out_format == RGB) { |
| - if (hdmi->hdmi_data.colorimetry == |
| - HDMI_COLORIMETRY_ITU_601) |
| - csc_coeff = &csc_coeff_rgb_out_eitu601; |
| - else |
| - csc_coeff = &csc_coeff_rgb_out_eitu709; |
| - } else if (hdmi->hdmi_data.enc_in_format == RGB) { |
| - if (hdmi->hdmi_data.colorimetry == |
| - HDMI_COLORIMETRY_ITU_601) |
| - csc_coeff = &csc_coeff_rgb_in_eitu601; |
| - else |
| - csc_coeff = &csc_coeff_rgb_in_eitu709; |
| - csc_scale = 0; |
| - } |
| - } |
| - |
| - /* The CSC registers are sequential, alternating MSB then LSB */ |
| - for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) { |
| - u16 coeff_a = (*csc_coeff)[0][i]; |
| - u16 coeff_b = (*csc_coeff)[1][i]; |
| - u16 coeff_c = (*csc_coeff)[2][i]; |
| - |
| - hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2); |
| - hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2); |
| - hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2); |
| - hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2); |
| - hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2); |
| - hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2); |
| - } |
| - |
| - hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK, |
| - HDMI_CSC_SCALE); |
| -} |
| - |
| -static void hdmi_video_csc(struct dw_hdmi *hdmi) |
| -{ |
| - int color_depth = 0; |
| - int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE; |
| - int decimation = 0; |
| - |
| - /* YCC422 interpolation to 444 mode */ |
| - if (is_color_space_interpolation(hdmi)) |
| - interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1; |
| - else if (is_color_space_decimation(hdmi)) |
| - decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3; |
| - |
| - if (hdmi->hdmi_data.enc_color_depth == 8) |
| - color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP; |
| - else if (hdmi->hdmi_data.enc_color_depth == 10) |
| - color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP; |
| - else if (hdmi->hdmi_data.enc_color_depth == 12) |
| - color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP; |
| - else if (hdmi->hdmi_data.enc_color_depth == 16) |
| - color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP; |
| - else |
| - return; |
| - |
| - /* Configure the CSC registers */ |
| - hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG); |
| - hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, |
| - HDMI_CSC_SCALE); |
| - |
| - dw_hdmi_update_csc_coeffs(hdmi); |
| -} |
| - |
| -/* |
| - * HDMI video packetizer is used to packetize the data. |
| - * for example, if input is YCC422 mode or repeater is used, |
| - * data should be repacked this module can be bypassed. |
| - */ |
| -static void hdmi_video_packetize(struct dw_hdmi *hdmi) |
| -{ |
| - unsigned int color_depth = 0; |
| - unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit; |
| - unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP; |
| - struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; |
| - u8 val, vp_conf; |
| - |
| - if (hdmi_data->enc_out_format == RGB || |
| - hdmi_data->enc_out_format == YCBCR444) { |
| - if (!hdmi_data->enc_color_depth) { |
| - output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; |
| - } else if (hdmi_data->enc_color_depth == 8) { |
| - color_depth = 4; |
| - output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; |
| - } else if (hdmi_data->enc_color_depth == 10) { |
| - color_depth = 5; |
| - } else if (hdmi_data->enc_color_depth == 12) { |
| - color_depth = 6; |
| - } else if (hdmi_data->enc_color_depth == 16) { |
| - color_depth = 7; |
| - } else { |
| - return; |
| - } |
| - } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) { |
| - if (!hdmi_data->enc_color_depth || |
| - hdmi_data->enc_color_depth == 8) |
| - remap_size = HDMI_VP_REMAP_YCC422_16bit; |
| - else if (hdmi_data->enc_color_depth == 10) |
| - remap_size = HDMI_VP_REMAP_YCC422_20bit; |
| - else if (hdmi_data->enc_color_depth == 12) |
| - remap_size = HDMI_VP_REMAP_YCC422_24bit; |
| - else |
| - return; |
| - output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422; |
| - } else { |
| - return; |
| - } |
| - |
| - /* set the packetizer registers */ |
| - val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & |
| - HDMI_VP_PR_CD_COLOR_DEPTH_MASK) | |
| - ((hdmi_data->pix_repet_factor << |
| - HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) & |
| - HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK); |
| - hdmi_writeb(hdmi, val, HDMI_VP_PR_CD); |
| - |
| - hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE, |
| - HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF); |
| - |
| - /* Data from pixel repeater block */ |
| - if (hdmi_data->pix_repet_factor > 1) { |
| - vp_conf = HDMI_VP_CONF_PR_EN_ENABLE | |
| - HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER; |
| - } else { /* data from packetizer block */ |
| - vp_conf = HDMI_VP_CONF_PR_EN_DISABLE | |
| - HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER; |
| - } |
| - |
| - hdmi_modb(hdmi, vp_conf, |
| - HDMI_VP_CONF_PR_EN_MASK | |
| - HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF); |
| - |
| - hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET, |
| - HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF); |
| - |
| - hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP); |
| - |
| - if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) { |
| - vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE | |
| - HDMI_VP_CONF_PP_EN_ENABLE | |
| - HDMI_VP_CONF_YCC422_EN_DISABLE; |
| - } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) { |
| - vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE | |
| - HDMI_VP_CONF_PP_EN_DISABLE | |
| - HDMI_VP_CONF_YCC422_EN_ENABLE; |
| - } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) { |
| - vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE | |
| - HDMI_VP_CONF_PP_EN_DISABLE | |
| - HDMI_VP_CONF_YCC422_EN_DISABLE; |
| - } else { |
| - return; |
| - } |
| - |
| - hdmi_modb(hdmi, vp_conf, |
| - HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK | |
| - HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF); |
| - |
| - hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE | |
| - HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE, |
| - HDMI_VP_STUFF_PP_STUFFING_MASK | |
| - HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF); |
| - |
| - hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK, |
| - HDMI_VP_CONF); |
| -} |
| - |
| -/* ----------------------------------------------------------------------------- |
| - * Synopsys PHY Handling |
| - */ |
| - |
| -static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, |
| - unsigned char bit) |
| -{ |
| - hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET, |
| - HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0); |
| -} |
| - |
| -static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec) |
| -{ |
| - u32 val; |
| - |
| - while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) { |
| - if (msec-- == 0) |
| - return false; |
| - udelay(1000); |
| - } |
| - hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0); |
| - |
| - return true; |
| -} |
| - |
| -void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, |
| - unsigned char addr) |
| -{ |
| - hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); |
| - hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); |
| - hdmi_writeb(hdmi, (unsigned char)(data >> 8), |
| - HDMI_PHY_I2CM_DATAO_1_ADDR); |
| - hdmi_writeb(hdmi, (unsigned char)(data >> 0), |
| - HDMI_PHY_I2CM_DATAO_0_ADDR); |
| - hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, |
| - HDMI_PHY_I2CM_OPERATION_ADDR); |
| - hdmi_phy_wait_i2c_done(hdmi, 1000); |
| -} |
| -EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write); |
| - |
| -static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable) |
| -{ |
| - hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0, |
| - HDMI_PHY_CONF0_PDZ_OFFSET, |
| - HDMI_PHY_CONF0_PDZ_MASK); |
| -} |
| - |
| -static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable) |
| -{ |
| - hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| - HDMI_PHY_CONF0_ENTMDS_OFFSET, |
| - HDMI_PHY_CONF0_ENTMDS_MASK); |
| -} |
| - |
| -static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable) |
| -{ |
| - hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| - HDMI_PHY_CONF0_SVSRET_OFFSET, |
| - HDMI_PHY_CONF0_SVSRET_MASK); |
| -} |
| - |
| -static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable) |
| -{ |
| - hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| - HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, |
| - HDMI_PHY_CONF0_GEN2_PDDQ_MASK); |
| -} |
| - |
| -static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable) |
| -{ |
| - hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| - HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, |
| - HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); |
| -} |
| - |
| -static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable) |
| -{ |
| - hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| - HDMI_PHY_CONF0_SELDATAENPOL_OFFSET, |
| - HDMI_PHY_CONF0_SELDATAENPOL_MASK); |
| -} |
| - |
| -static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable) |
| -{ |
| - hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| - HDMI_PHY_CONF0_SELDIPIF_OFFSET, |
| - HDMI_PHY_CONF0_SELDIPIF_MASK); |
| -} |
| - |
| -static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) |
| -{ |
| - const struct dw_hdmi_phy_data *phy = hdmi->phy.data; |
| - unsigned int i; |
| - u16 val; |
| - |
| - if (phy->gen == 1) { |
| - dw_hdmi_phy_enable_tmds(hdmi, 0); |
| - dw_hdmi_phy_enable_powerdown(hdmi, true); |
| - return; |
| - } |
| - |
| - dw_hdmi_phy_gen2_txpwron(hdmi, 0); |
| - |
| - /* |
| - * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went |
| - * to low power mode. |
| - */ |
| - for (i = 0; i < 5; ++i) { |
| - val = hdmi_readb(hdmi, HDMI_PHY_STAT0); |
| - if (!(val & HDMI_PHY_TX_PHY_LOCK)) |
| - break; |
| - |
| - usleep_range(1000, 2000); |
| - } |
| - |
| - if (val & HDMI_PHY_TX_PHY_LOCK) |
| - dev_warn(hdmi->dev, "PHY failed to power down\n"); |
| - else |
| - dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i); |
| - |
| - dw_hdmi_phy_gen2_pddq(hdmi, 1); |
| -} |
| - |
| -static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) |
| -{ |
| - const struct dw_hdmi_phy_data *phy = hdmi->phy.data; |
| - unsigned int i; |
| - u8 val; |
| - |
| - if (phy->gen == 1) { |
| - dw_hdmi_phy_enable_powerdown(hdmi, false); |
| - |
| - /* Toggle TMDS enable. */ |
| - dw_hdmi_phy_enable_tmds(hdmi, 0); |
| - dw_hdmi_phy_enable_tmds(hdmi, 1); |
| - return 0; |
| - } |
| - |
| - dw_hdmi_phy_gen2_txpwron(hdmi, 1); |
| - dw_hdmi_phy_gen2_pddq(hdmi, 0); |
| - |
| - /* Wait for PHY PLL lock */ |
| - for (i = 0; i < 5; ++i) { |
| - val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; |
| - if (val) |
| - break; |
| - |
| - usleep_range(1000, 2000); |
| - } |
| - |
| - if (!val) { |
| - dev_err(hdmi->dev, "PHY PLL failed to lock\n"); |
| - return -ETIMEDOUT; |
| - } |
| - |
| - dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i); |
| - return 0; |
| -} |
| - |
| -/* |
| - * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available |
| - * information the DWC MHL PHY has the same register layout and is thus also |
| - * supported by this function. |
| - */ |
| -static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, |
| - const struct dw_hdmi_plat_data *pdata, |
| - unsigned long mpixelclock) |
| -{ |
| - const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; |
| - const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; |
| - const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; |
| - |
| - /* PLL/MPLL Cfg - always match on final entry */ |
| - for (; mpll_config->mpixelclock != ~0UL; mpll_config++) |
| - if (mpixelclock <= mpll_config->mpixelclock) |
| - break; |
| - |
| - for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) |
| - if (mpixelclock <= curr_ctrl->mpixelclock) |
| - break; |
| - |
| - for (; phy_config->mpixelclock != ~0UL; phy_config++) |
| - if (mpixelclock <= phy_config->mpixelclock) |
| - break; |
| - |
| - if (mpll_config->mpixelclock == ~0UL || |
| - curr_ctrl->mpixelclock == ~0UL || |
| - phy_config->mpixelclock == ~0UL) |
| - return -EINVAL; |
| - |
| - dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, |
| - HDMI_3D_TX_PHY_CPCE_CTRL); |
| - dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, |
| - HDMI_3D_TX_PHY_GMPCTRL); |
| - dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], |
| - HDMI_3D_TX_PHY_CURRCTRL); |
| - |
| - dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); |
| - dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK, |
| - HDMI_3D_TX_PHY_MSM_CTRL); |
| - |
| - dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM); |
| - dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, |
| - HDMI_3D_TX_PHY_CKSYMTXCTRL); |
| - dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, |
| - HDMI_3D_TX_PHY_VLEVCTRL); |
| - |
| - /* Override and disable clock termination. */ |
| - dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE, |
| - HDMI_3D_TX_PHY_CKCALCTRL); |
| - |
| - return 0; |
| -} |
| - |
| -static int hdmi_phy_configure(struct dw_hdmi *hdmi) |
| -{ |
| - const struct dw_hdmi_phy_data *phy = hdmi->phy.data; |
| - const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; |
| - unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock; |
| - int ret; |
| - |
| - dw_hdmi_phy_power_off(hdmi); |
| - |
| - /* Leave low power consumption mode by asserting SVSRET. */ |
| - if (phy->has_svsret) |
| - dw_hdmi_phy_enable_svsret(hdmi, 1); |
| - |
| - /* PHY reset. The reset signal is active high on Gen2 PHYs. */ |
| - hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ); |
| - hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ); |
| - |
| - hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST); |
| - |
| - hdmi_phy_test_clear(hdmi, 1); |
| - hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, |
| - HDMI_PHY_I2CM_SLAVE_ADDR); |
| - hdmi_phy_test_clear(hdmi, 0); |
| - |
| - /* Write to the PHY as configured by the platform */ |
| - if (pdata->configure_phy) |
| - ret = pdata->configure_phy(hdmi, pdata, mpixelclock); |
| - else |
| - ret = phy->configure(hdmi, pdata, mpixelclock); |
| - if (ret) { |
| - dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n", |
| - mpixelclock); |
| - return ret; |
| - } |
| - |
| - return dw_hdmi_phy_power_on(hdmi); |
| -} |
| - |
| -static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, |
| - struct drm_display_mode *mode) |
| -{ |
| - int i, ret; |
| - |
| - /* HDMI Phy spec says to do the phy initialization sequence twice */ |
| - for (i = 0; i < 2; i++) { |
| - dw_hdmi_phy_sel_data_en_pol(hdmi, 1); |
| - dw_hdmi_phy_sel_interface_control(hdmi, 0); |
| - |
| - ret = hdmi_phy_configure(hdmi); |
| - if (ret) |
| - return ret; |
| - } |
| - |
| - return 0; |
| -} |
| - |
| -static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) |
| -{ |
| - dw_hdmi_phy_power_off(hdmi); |
| -} |
| - |
| -static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, |
| - void *data) |
| -{ |
| - return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? |
| - connector_status_connected : connector_status_disconnected; |
| -} |
| - |
| -static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { |
| - .init = dw_hdmi_phy_init, |
| - .disable = dw_hdmi_phy_disable, |
| - .read_hpd = dw_hdmi_phy_read_hpd, |
| -}; |
| - |
| -/* ----------------------------------------------------------------------------- |
| - * HDMI TX Setup |
| - */ |
| - |
| -static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) |
| -{ |
| - u8 de; |
| - |
| - if (hdmi->hdmi_data.video_mode.mdataenablepolarity) |
| - de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH; |
| - else |
| - de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW; |
| - |
| - /* disable rx detect */ |
| - hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE, |
| - HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0); |
| - |
| - hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG); |
| - |
| - hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE, |
| - HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); |
| -} |
| - |
| -static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) |
| -{ |
| - struct hdmi_avi_infoframe frame; |
| - u8 val; |
| - |
| - /* Initialise info frame from DRM mode */ |
| - drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); |
| - |
| - if (hdmi->hdmi_data.enc_out_format == YCBCR444) |
| - frame.colorspace = HDMI_COLORSPACE_YUV444; |
| - else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) |
| - frame.colorspace = HDMI_COLORSPACE_YUV422; |
| - else |
| - frame.colorspace = HDMI_COLORSPACE_RGB; |
| - |
| - /* Set up colorimetry */ |
| - if (hdmi->hdmi_data.enc_out_format == XVYCC444) { |
| - frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; |
| - if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) |
| - frame.extended_colorimetry = |
| - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
| - else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/ |
| - frame.extended_colorimetry = |
| - HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; |
| - } else if (hdmi->hdmi_data.enc_out_format != RGB) { |
| - frame.colorimetry = hdmi->hdmi_data.colorimetry; |
| - frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
| - } else { /* Carries no data */ |
| - frame.colorimetry = HDMI_COLORIMETRY_NONE; |
| - frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
| - } |
| - |
| - frame.scan_mode = HDMI_SCAN_MODE_NONE; |
| - |
| - /* |
| - * The Designware IP uses a different byte format from standard |
| - * AVI info frames, though generally the bits are in the correct |
| - * bytes. |
| - */ |
| - |
| - /* |
| - * AVI data byte 1 differences: Colorspace in bits 0,1 rather than 5,6, |
| - * scan info in bits 4,5 rather than 0,1 and active aspect present in |
| - * bit 6 rather than 4. |
| - */ |
| - val = (frame.scan_mode & 3) << 4 | (frame.colorspace & 3); |
| - if (frame.active_aspect & 15) |
| - val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT; |
| - if (frame.top_bar || frame.bottom_bar) |
| - val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR; |
| - if (frame.left_bar || frame.right_bar) |
| - val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR; |
| - hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0); |
| - |
| - /* AVI data byte 2 differences: none */ |
| - val = ((frame.colorimetry & 0x3) << 6) | |
| - ((frame.picture_aspect & 0x3) << 4) | |
| - (frame.active_aspect & 0xf); |
| - hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1); |
| - |
| - /* AVI data byte 3 differences: none */ |
| - val = ((frame.extended_colorimetry & 0x7) << 4) | |
| - ((frame.quantization_range & 0x3) << 2) | |
| - (frame.nups & 0x3); |
| - if (frame.itc) |
| - val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID; |
| - hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2); |
| - |
| - /* AVI data byte 4 differences: none */ |
| - val = frame.video_code & 0x7f; |
| - hdmi_writeb(hdmi, val, HDMI_FC_AVIVID); |
| - |
| - /* AVI Data Byte 5- set up input and output pixel repetition */ |
| - val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) << |
| - HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) & |
| - HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) | |
| - ((hdmi->hdmi_data.video_mode.mpixelrepetitionoutput << |
| - HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) & |
| - HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK); |
| - hdmi_writeb(hdmi, val, HDMI_FC_PRCONF); |
| - |
| - /* |
| - * AVI data byte 5 differences: content type in 0,1 rather than 4,5, |
| - * ycc range in bits 2,3 rather than 6,7 |
| - */ |
| - val = ((frame.ycc_quantization_range & 0x3) << 2) | |
| - (frame.content_type & 0x3); |
| - hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3); |
| - |
| - /* AVI Data Bytes 6-13 */ |
| - hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0); |
| - hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1); |
| - hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0); |
| - hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1); |
| - hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0); |
| - hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1); |
| - hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0); |
| - hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1); |
| -} |
| - |
| -static void hdmi_av_composer(struct dw_hdmi *hdmi, |
| - const struct drm_display_mode *mode) |
| -{ |
| - u8 inv_val; |
| - struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; |
| - int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; |
| - unsigned int vdisplay; |
| - |
| - vmode->mpixelclock = mode->clock * 1000; |
| - |
| - dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); |
| - |
| - /* Set up HDMI_FC_INVIDCONF */ |
| - inv_val = (hdmi->hdmi_data.hdcp_enable ? |
| - HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : |
| - HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE); |
| - |
| - inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ? |
| - HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH : |
| - HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW; |
| - |
| - inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ? |
| - HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH : |
| - HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW; |
| - |
| - inv_val |= (vmode->mdataenablepolarity ? |
| - HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH : |
| - HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW); |
| - |
| - if (hdmi->vic == 39) |
| - inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH; |
| - else |
| - inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ? |
| - HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH : |
| - HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW; |
| - |
| - inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ? |
| - HDMI_FC_INVIDCONF_IN_I_P_INTERLACED : |
| - HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE; |
| - |
| - inv_val |= hdmi->sink_is_hdmi ? |
| - HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE : |
| - HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE; |
| - |
| - hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF); |
| - |
| - vdisplay = mode->vdisplay; |
| - vblank = mode->vtotal - mode->vdisplay; |
| - v_de_vs = mode->vsync_start - mode->vdisplay; |
| - vsync_len = mode->vsync_end - mode->vsync_start; |
| - |
| - /* |
| - * When we're setting an interlaced mode, we need |
| - * to adjust the vertical timing to suit. |
| - */ |
| - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
| - vdisplay /= 2; |
| - vblank /= 2; |
| - v_de_vs /= 2; |
| - vsync_len /= 2; |
| - } |
| - |
| - /* Set up horizontal active pixel width */ |
| - hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1); |
| - hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0); |
| - |
| - /* Set up vertical active lines */ |
| - hdmi_writeb(hdmi, vdisplay >> 8, HDMI_FC_INVACTV1); |
| - hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0); |
| - |
| - /* Set up horizontal blanking pixel region width */ |
| - hblank = mode->htotal - mode->hdisplay; |
| - hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1); |
| - hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0); |
| - |
| - /* Set up vertical blanking pixel region width */ |
| - hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK); |
| - |
| - /* Set up HSYNC active edge delay width (in pixel clks) */ |
| - h_de_hs = mode->hsync_start - mode->hdisplay; |
| - hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1); |
| - hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0); |
| - |
| - /* Set up VSYNC active edge delay (in lines) */ |
| - hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY); |
| - |
| - /* Set up HSYNC active pulse width (in pixel clks) */ |
| - hsync_len = mode->hsync_end - mode->hsync_start; |
| - hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1); |
| - hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0); |
| - |
| - /* Set up VSYNC active edge delay (in lines) */ |
| - hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH); |
| -} |
| - |
| -/* HDMI Initialization Step B.4 */ |
| -static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) |
| -{ |
| - u8 clkdis; |
| - |
| - /* control period minimum duration */ |
| - hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR); |
| - hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR); |
| - hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC); |
| - |
| - /* Set to fill TMDS data channels */ |
| - hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM); |
| - hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM); |
| - hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM); |
| - |
| - /* Enable pixel clock and tmds data path */ |
| - clkdis = 0x7F; |
| - clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; |
| - hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); |
| - |
| - clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE; |
| - hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); |
| - |
| - /* Enable csc path */ |
| - if (is_color_space_conversion(hdmi)) { |
| - clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; |
| - hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); |
| - } |
| - |
| - /* Enable color space conversion if needed */ |
| - if (is_color_space_conversion(hdmi)) |
| - hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH, |
| - HDMI_MC_FLOWCTRL); |
| - else |
| - hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS, |
| - HDMI_MC_FLOWCTRL); |
| -} |
| - |
| -static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi) |
| -{ |
| - hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS); |
| -} |
| - |
| -/* Workaround to clear the overflow condition */ |
| -static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) |
| -{ |
| - unsigned int count; |
| - unsigned int i; |
| - u8 val; |
| - |
| - /* |
| - * Under some circumstances the Frame Composer arithmetic unit can miss |
| - * an FC register write due to being busy processing the previous one. |
| - * The issue can be worked around by issuing a TMDS software reset and |
| - * then write one of the FC registers several times. |
| - * |
| - * The number of iterations matters and depends on the HDMI TX revision |
| - * (and possibly on the platform). So far only i.MX6Q (v1.30a) and |
| - * i.MX6DL (v1.31a) have been identified as needing the workaround, with |
| - * 4 and 1 iterations respectively. |
| - */ |
| - |
| - switch (hdmi->version) { |
| - case 0x130a: |
| - count = 4; |
| - break; |
| - case 0x131a: |
| - count = 1; |
| - break; |
| - default: |
| - return; |
| - } |
| - |
| - /* TMDS software reset */ |
| - hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ); |
| - |
| - val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF); |
| - for (i = 0; i < count; i++) |
| - hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF); |
| -} |
| - |
| -static void hdmi_enable_overflow_interrupts(struct dw_hdmi *hdmi) |
| -{ |
| - hdmi_writeb(hdmi, 0, HDMI_FC_MASK2); |
| - hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2); |
| -} |
| - |
| -static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) |
| -{ |
| - hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK, |
| - HDMI_IH_MUTE_FC_STAT2); |
| -} |
| - |
| -static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) |
| -{ |
| - int ret; |
| - |
| - hdmi_disable_overflow_interrupts(hdmi); |
| - |
| - hdmi->vic = drm_match_cea_mode(mode); |
| - |
| - if (!hdmi->vic) { |
| - dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n"); |
| - } else { |
| - dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic); |
| - } |
| - |
| - if ((hdmi->vic == 6) || (hdmi->vic == 7) || |
| - (hdmi->vic == 21) || (hdmi->vic == 22) || |
| - (hdmi->vic == 2) || (hdmi->vic == 3) || |
| - (hdmi->vic == 17) || (hdmi->vic == 18)) |
| - hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; |
| - else |
| - hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; |
| - |
| - hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; |
| - hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; |
| - |
| - /* TODO: Get input format from IPU (via FB driver interface) */ |
| - hdmi->hdmi_data.enc_in_format = RGB; |
| - |
| - hdmi->hdmi_data.enc_out_format = RGB; |
| - |
| - hdmi->hdmi_data.enc_color_depth = 8; |
| - hdmi->hdmi_data.pix_repet_factor = 0; |
| - hdmi->hdmi_data.hdcp_enable = 0; |
| - hdmi->hdmi_data.video_mode.mdataenablepolarity = true; |
| - |
| - /* HDMI Initialization Step B.1 */ |
| - hdmi_av_composer(hdmi, mode); |
| - |
| - /* HDMI Initializateion Step B.2 */ |
| - ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode); |
| - if (ret) |
| - return ret; |
| - hdmi->phy.enabled = true; |
| - |
| - /* HDMI Initialization Step B.3 */ |
| - dw_hdmi_enable_video_path(hdmi); |
| - |
| - if (hdmi->sink_has_audio) { |
| - dev_dbg(hdmi->dev, "sink has audio support\n"); |
| - |
| - /* HDMI Initialization Step E - Configure audio */ |
| - hdmi_clk_regenerator_update_pixel_clock(hdmi); |
| - hdmi_enable_audio_clk(hdmi); |
| - } |
| - |
| - /* not for DVI mode */ |
| - if (hdmi->sink_is_hdmi) { |
| - dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); |
| - |
| - /* HDMI Initialization Step F - Configure AVI InfoFrame */ |
| - hdmi_config_AVI(hdmi, mode); |
| - } else { |
| - dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); |
| - } |
| - |
| - hdmi_video_packetize(hdmi); |
| - hdmi_video_csc(hdmi); |
| - hdmi_video_sample(hdmi); |
| - hdmi_tx_hdcp_config(hdmi); |
| - |
| - dw_hdmi_clear_overflow(hdmi); |
| - if (hdmi->cable_plugin && hdmi->sink_is_hdmi) |
| - hdmi_enable_overflow_interrupts(hdmi); |
| - |
| - return 0; |
| -} |
| - |
| -/* Wait until we are registered to enable interrupts */ |
| -static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi) |
| -{ |
| - hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, |
| - HDMI_PHY_I2CM_INT_ADDR); |
| - |
| - hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL | |
| - HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL, |
| - HDMI_PHY_I2CM_CTLINT_ADDR); |
| - |
| - /* enable cable hot plug irq */ |
| - hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); |
| - |
| - /* Clear Hotplug interrupts */ |
| - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, |
| - HDMI_IH_PHY_STAT0); |
| - |
| - return 0; |
| -} |
| - |
| -static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) |
| -{ |
| - u8 ih_mute; |
| - |
| - /* |
| - * Boot up defaults are: |
| - * HDMI_IH_MUTE = 0x03 (disabled) |
| - * HDMI_IH_MUTE_* = 0x00 (enabled) |
| - * |
| - * Disable top level interrupt bits in HDMI block |
| - */ |
| - ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) | |
| - HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT | |
| - HDMI_IH_MUTE_MUTE_ALL_INTERRUPT; |
| - |
| - hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); |
| - |
| - /* by default mask all interrupts */ |
| - hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK); |
| - hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1); |
| - hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2); |
| - hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR); |
| - hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR); |
| - hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT); |
| - hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT); |
| - hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK); |
| - hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK); |
| - hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK); |
| - hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK); |
| - hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT); |
| - hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT); |
| - |
| - /* Disable interrupts in the IH_MUTE_* registers */ |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0); |
| - hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0); |
| - |
| - /* Enable top level interrupt bits in HDMI block */ |
| - ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT | |
| - HDMI_IH_MUTE_MUTE_ALL_INTERRUPT); |
| - hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); |
| -} |
| - |
| -static void dw_hdmi_poweron(struct dw_hdmi *hdmi) |
| -{ |
| - hdmi->bridge_is_on = true; |
| - dw_hdmi_setup(hdmi, &hdmi->previous_mode); |
| -} |
| - |
| -static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) |
| -{ |
| - if (hdmi->phy.enabled) { |
| - hdmi->phy.ops->disable(hdmi, hdmi->phy.data); |
| - hdmi->phy.enabled = false; |
| - } |
| - |
| - hdmi->bridge_is_on = false; |
| -} |
| - |
| -static void dw_hdmi_update_power(struct dw_hdmi *hdmi) |
| -{ |
| - int force = hdmi->force; |
| - |
| - if (hdmi->disabled) { |
| - force = DRM_FORCE_OFF; |
| - } else if (force == DRM_FORCE_UNSPECIFIED) { |
| - if (hdmi->rxsense) |
| - force = DRM_FORCE_ON; |
| - else |
| - force = DRM_FORCE_OFF; |
| - } |
| - |
| - if (force == DRM_FORCE_OFF) { |
| - if (hdmi->bridge_is_on) |
| - dw_hdmi_poweroff(hdmi); |
| - } else { |
| - if (!hdmi->bridge_is_on) |
| - dw_hdmi_poweron(hdmi); |
| - } |
| -} |
| - |
| -/* |
| - * Adjust the detection of RXSENSE according to whether we have a forced |
| - * connection mode enabled, or whether we have been disabled. There is |
| - * no point processing RXSENSE interrupts if we have a forced connection |
| - * state, or DRM has us disabled. |
| - * |
| - * We also disable rxsense interrupts when we think we're disconnected |
| - * to avoid floating TDMS signals giving false rxsense interrupts. |
| - * |
| - * Note: we still need to listen for HPD interrupts even when DRM has us |
| - * disabled so that we can detect a connect event. |
| - */ |
| -static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) |
| -{ |
| - u8 old_mask = hdmi->phy_mask; |
| - |
| - if (hdmi->force || hdmi->disabled || !hdmi->rxsense) |
| - hdmi->phy_mask |= HDMI_PHY_RX_SENSE; |
| - else |
| - hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE; |
| - |
| - if (old_mask != hdmi->phy_mask) |
| - hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); |
| -} |
| - |
| -static enum drm_connector_status |
| -dw_hdmi_connector_detect(struct drm_connector *connector, bool force) |
| -{ |
| - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, |
| - connector); |
| - |
| - mutex_lock(&hdmi->mutex); |
| - hdmi->force = DRM_FORCE_UNSPECIFIED; |
| - dw_hdmi_update_power(hdmi); |
| - dw_hdmi_update_phy_mask(hdmi); |
| - mutex_unlock(&hdmi->mutex); |
| - |
| - return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); |
| -} |
| - |
| -static int dw_hdmi_connector_get_modes(struct drm_connector *connector) |
| -{ |
| - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, |
| - connector); |
| - struct edid *edid; |
| - int ret = 0; |
| - |
| - if (!hdmi->ddc) |
| - return 0; |
| - |
| - edid = drm_get_edid(connector, hdmi->ddc); |
| - if (edid) { |
| - dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", |
| - edid->width_cm, edid->height_cm); |
| - |
| - hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); |
| - hdmi->sink_has_audio = drm_detect_monitor_audio(edid); |
| - drm_mode_connector_update_edid_property(connector, edid); |
| - ret = drm_add_edid_modes(connector, edid); |
| - /* Store the ELD */ |
| - drm_edid_to_eld(connector, edid); |
| - kfree(edid); |
| - } else { |
| - dev_dbg(hdmi->dev, "failed to get edid\n"); |
| - } |
| - |
| - return ret; |
| -} |
| - |
| -static enum drm_mode_status |
| -dw_hdmi_connector_mode_valid(struct drm_connector *connector, |
| - struct drm_display_mode *mode) |
| -{ |
| - struct dw_hdmi *hdmi = container_of(connector, |
| - struct dw_hdmi, connector); |
| - enum drm_mode_status mode_status = MODE_OK; |
| - |
| - /* We don't support double-clocked modes */ |
| - if (mode->flags & DRM_MODE_FLAG_DBLCLK) |
| - return MODE_BAD; |
| - |
| - if (hdmi->plat_data->mode_valid) |
| - mode_status = hdmi->plat_data->mode_valid(connector, mode); |
| - |
| - return mode_status; |
| -} |
| - |
| -static void dw_hdmi_connector_force(struct drm_connector *connector) |
| -{ |
| - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, |
| - connector); |
| - |
| - mutex_lock(&hdmi->mutex); |
| - hdmi->force = connector->force; |
| - dw_hdmi_update_power(hdmi); |
| - dw_hdmi_update_phy_mask(hdmi); |
| - mutex_unlock(&hdmi->mutex); |
| -} |
| - |
| -static const struct drm_connector_funcs dw_hdmi_connector_funcs = { |
| - .dpms = drm_atomic_helper_connector_dpms, |
| - .fill_modes = drm_helper_probe_single_connector_modes, |
| - .detect = dw_hdmi_connector_detect, |
| - .destroy = drm_connector_cleanup, |
| - .force = dw_hdmi_connector_force, |
| - .reset = drm_atomic_helper_connector_reset, |
| - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
| - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
| -}; |
| - |
| -static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { |
| - .get_modes = dw_hdmi_connector_get_modes, |
| - .mode_valid = dw_hdmi_connector_mode_valid, |
| - .best_encoder = drm_atomic_helper_best_encoder, |
| -}; |
| - |
| -static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) |
| -{ |
| - struct dw_hdmi *hdmi = bridge->driver_private; |
| - struct drm_encoder *encoder = bridge->encoder; |
| - struct drm_connector *connector = &hdmi->connector; |
| - |
| - connector->interlace_allowed = 1; |
| - connector->polled = DRM_CONNECTOR_POLL_HPD; |
| - |
| - drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); |
| - |
| - drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs, |
| - DRM_MODE_CONNECTOR_HDMIA); |
| - |
| - drm_mode_connector_attach_encoder(connector, encoder); |
| - |
| - return 0; |
| -} |
| - |
| -static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, |
| - struct drm_display_mode *orig_mode, |
| - struct drm_display_mode *mode) |
| -{ |
| - struct dw_hdmi *hdmi = bridge->driver_private; |
| - |
| - mutex_lock(&hdmi->mutex); |
| - |
| - /* Store the display mode for plugin/DKMS poweron events */ |
| - memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); |
| - |
| - mutex_unlock(&hdmi->mutex); |
| -} |
| - |
| -static void dw_hdmi_bridge_disable(struct drm_bridge *bridge) |
| -{ |
| - struct dw_hdmi *hdmi = bridge->driver_private; |
| - |
| - mutex_lock(&hdmi->mutex); |
| - hdmi->disabled = true; |
| - dw_hdmi_update_power(hdmi); |
| - dw_hdmi_update_phy_mask(hdmi); |
| - mutex_unlock(&hdmi->mutex); |
| -} |
| - |
| -static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) |
| -{ |
| - struct dw_hdmi *hdmi = bridge->driver_private; |
| - |
| - mutex_lock(&hdmi->mutex); |
| - hdmi->disabled = false; |
| - dw_hdmi_update_power(hdmi); |
| - dw_hdmi_update_phy_mask(hdmi); |
| - mutex_unlock(&hdmi->mutex); |
| -} |
| - |
| -static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { |
| - .attach = dw_hdmi_bridge_attach, |
| - .enable = dw_hdmi_bridge_enable, |
| - .disable = dw_hdmi_bridge_disable, |
| - .mode_set = dw_hdmi_bridge_mode_set, |
| -}; |
| - |
| -static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi) |
| -{ |
| - struct dw_hdmi_i2c *i2c = hdmi->i2c; |
| - unsigned int stat; |
| - |
| - stat = hdmi_readb(hdmi, HDMI_IH_I2CM_STAT0); |
| - if (!stat) |
| - return IRQ_NONE; |
| - |
| - hdmi_writeb(hdmi, stat, HDMI_IH_I2CM_STAT0); |
| - |
| - i2c->stat = stat; |
| - |
| - complete(&i2c->cmp); |
| - |
| - return IRQ_HANDLED; |
| -} |
| - |
| -static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) |
| -{ |
| - struct dw_hdmi *hdmi = dev_id; |
| - u8 intr_stat; |
| - irqreturn_t ret = IRQ_NONE; |
| - |
| - if (hdmi->i2c) |
| - ret = dw_hdmi_i2c_irq(hdmi); |
| - |
| - intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); |
| - if (intr_stat) { |
| - hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); |
| - return IRQ_WAKE_THREAD; |
| - } |
| - |
| - return ret; |
| -} |
| - |
| -static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) |
| -{ |
| - struct dw_hdmi *hdmi = dev_id; |
| - u8 intr_stat, phy_int_pol, phy_pol_mask, phy_stat; |
| - |
| - intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); |
| - phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); |
| - phy_stat = hdmi_readb(hdmi, HDMI_PHY_STAT0); |
| - |
| - phy_pol_mask = 0; |
| - if (intr_stat & HDMI_IH_PHY_STAT0_HPD) |
| - phy_pol_mask |= HDMI_PHY_HPD; |
| - if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE0) |
| - phy_pol_mask |= HDMI_PHY_RX_SENSE0; |
| - if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE1) |
| - phy_pol_mask |= HDMI_PHY_RX_SENSE1; |
| - if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE2) |
| - phy_pol_mask |= HDMI_PHY_RX_SENSE2; |
| - if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE3) |
| - phy_pol_mask |= HDMI_PHY_RX_SENSE3; |
| - |
| - if (phy_pol_mask) |
| - hdmi_modb(hdmi, ~phy_int_pol, phy_pol_mask, HDMI_PHY_POL0); |
| - |
| - /* |
| - * RX sense tells us whether the TDMS transmitters are detecting |
| - * load - in other words, there's something listening on the |
| - * other end of the link. Use this to decide whether we should |
| - * power on the phy as HPD may be toggled by the sink to merely |
| - * ask the source to re-read the EDID. |
| - */ |
| - if (intr_stat & |
| - (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { |
| - mutex_lock(&hdmi->mutex); |
| - if (!hdmi->disabled && !hdmi->force) { |
| - /* |
| - * If the RX sense status indicates we're disconnected, |
| - * clear the software rxsense status. |
| - */ |
| - if (!(phy_stat & HDMI_PHY_RX_SENSE)) |
| - hdmi->rxsense = false; |
| - |
| - /* |
| - * Only set the software rxsense status when both |
| - * rxsense and hpd indicates we're connected. |
| - * This avoids what seems to be bad behaviour in |
| - * at least iMX6S versions of the phy. |
| - */ |
| - if (phy_stat & HDMI_PHY_HPD) |
| - hdmi->rxsense = true; |
| - |
| - dw_hdmi_update_power(hdmi); |
| - dw_hdmi_update_phy_mask(hdmi); |
| - } |
| - mutex_unlock(&hdmi->mutex); |
| - } |
| - |
| - if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { |
| - dev_dbg(hdmi->dev, "EVENT=%s\n", |
| - phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout"); |
| - if (hdmi->bridge.dev) |
| - drm_helper_hpd_irq_event(hdmi->bridge.dev); |
| - } |
| - |
| - hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0); |
| - hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), |
| - HDMI_IH_MUTE_PHY_STAT0); |
| - |
| - return IRQ_HANDLED; |
| -} |
| - |
| -static const struct dw_hdmi_phy_data dw_hdmi_phys[] = { |
| - { |
| - .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY, |
| - .name = "DWC HDMI TX PHY", |
| - .gen = 1, |
| - }, { |
| - .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC, |
| - .name = "DWC MHL PHY + HEAC PHY", |
| - .gen = 2, |
| - .has_svsret = true, |
| - .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, |
| - }, { |
| - .type = DW_HDMI_PHY_DWC_MHL_PHY, |
| - .name = "DWC MHL PHY", |
| - .gen = 2, |
| - .has_svsret = true, |
| - .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, |
| - }, { |
| - .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC, |
| - .name = "DWC HDMI 3D TX PHY + HEAC PHY", |
| - .gen = 2, |
| - .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, |
| - }, { |
| - .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY, |
| - .name = "DWC HDMI 3D TX PHY", |
| - .gen = 2, |
| - .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, |
| - }, { |
| - .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY, |
| - .name = "DWC HDMI 2.0 TX PHY", |
| - .gen = 2, |
| - .has_svsret = true, |
| - }, { |
| - .type = DW_HDMI_PHY_VENDOR_PHY, |
| - .name = "Vendor PHY", |
| - } |
| -}; |
| - |
| -static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) |
| -{ |
| - unsigned int i; |
| - u8 phy_type; |
| - |
| - phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID); |
| - |
| - if (phy_type == DW_HDMI_PHY_VENDOR_PHY) { |
| - /* Vendor PHYs require support from the glue layer. */ |
| - if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) { |
| - dev_err(hdmi->dev, |
| - "Vendor HDMI PHY not supported by glue layer\n"); |
| - return -ENODEV; |
| - } |
| - |
| - hdmi->phy.ops = hdmi->plat_data->phy_ops; |
| - hdmi->phy.data = hdmi->plat_data->phy_data; |
| - hdmi->phy.name = hdmi->plat_data->phy_name; |
| - return 0; |
| - } |
| - |
| - /* Synopsys PHYs are handled internally. */ |
| - for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) { |
| - if (dw_hdmi_phys[i].type == phy_type) { |
| - hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops; |
| - hdmi->phy.name = dw_hdmi_phys[i].name; |
| - hdmi->phy.data = (void *)&dw_hdmi_phys[i]; |
| - |
| - if (!dw_hdmi_phys[i].configure && |
| - !hdmi->plat_data->configure_phy) { |
| - dev_err(hdmi->dev, "%s requires platform support\n", |
| - hdmi->phy.name); |
| - return -ENODEV; |
| - } |
| - |
| - return 0; |
| - } |
| - } |
| - |
| - dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type); |
| - return -ENODEV; |
| -} |
| - |
| -static const struct regmap_config hdmi_regmap_8bit_config = { |
| - .reg_bits = 32, |
| - .val_bits = 8, |
| - .reg_stride = 1, |
| - .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR, |
| -}; |
| - |
| -static const struct regmap_config hdmi_regmap_32bit_config = { |
| - .reg_bits = 32, |
| - .val_bits = 32, |
| - .reg_stride = 4, |
| - .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2, |
| -}; |
| - |
| -static struct dw_hdmi * |
| -__dw_hdmi_probe(struct platform_device *pdev, |
| - const struct dw_hdmi_plat_data *plat_data) |
| -{ |
| - struct device *dev = &pdev->dev; |
| - struct device_node *np = dev->of_node; |
| - struct platform_device_info pdevinfo; |
| - struct device_node *ddc_node; |
| - struct dw_hdmi *hdmi; |
| - struct resource *iores = NULL; |
| - int irq; |
| - int ret; |
| - u32 val = 1; |
| - u8 prod_id0; |
| - u8 prod_id1; |
| - u8 config0; |
| - u8 config3; |
| - |
| - hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); |
| - if (!hdmi) |
| - return ERR_PTR(-ENOMEM); |
| - |
| - hdmi->plat_data = plat_data; |
| - hdmi->dev = dev; |
| - hdmi->sample_rate = 48000; |
| - hdmi->disabled = true; |
| - hdmi->rxsense = true; |
| - hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE); |
| - |
| - mutex_init(&hdmi->mutex); |
| - mutex_init(&hdmi->audio_mutex); |
| - spin_lock_init(&hdmi->audio_lock); |
| - |
| - ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); |
| - if (ddc_node) { |
| - hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); |
| - of_node_put(ddc_node); |
| - if (!hdmi->ddc) { |
| - dev_dbg(hdmi->dev, "failed to read ddc node\n"); |
| - return ERR_PTR(-EPROBE_DEFER); |
| - } |
| - |
| - } else { |
| - dev_dbg(hdmi->dev, "no ddc property found\n"); |
| - } |
| - |
| - if (!plat_data->regm) { |
| - const struct regmap_config *reg_config; |
| - |
| - of_property_read_u32(np, "reg-io-width", &val); |
| - switch (val) { |
| - case 4: |
| - reg_config = &hdmi_regmap_32bit_config; |
| - hdmi->reg_shift = 2; |
| - break; |
| - case 1: |
| - reg_config = &hdmi_regmap_8bit_config; |
| - break; |
| - default: |
| - dev_err(dev, "reg-io-width must be 1 or 4\n"); |
| - return ERR_PTR(-EINVAL); |
| - } |
| - |
| - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| - hdmi->regs = devm_ioremap_resource(dev, iores); |
| - if (IS_ERR(hdmi->regs)) { |
| - ret = PTR_ERR(hdmi->regs); |
| - goto err_res; |
| - } |
| - |
| - hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config); |
| - if (IS_ERR(hdmi->regm)) { |
| - dev_err(dev, "Failed to configure regmap\n"); |
| - ret = PTR_ERR(hdmi->regm); |
| - goto err_res; |
| - } |
| - } else { |
| - hdmi->regm = plat_data->regm; |
| - } |
| - |
| - hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); |
| - if (IS_ERR(hdmi->isfr_clk)) { |
| - ret = PTR_ERR(hdmi->isfr_clk); |
| - dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret); |
| - goto err_res; |
| - } |
| - |
| - ret = clk_prepare_enable(hdmi->isfr_clk); |
| - if (ret) { |
| - dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret); |
| - goto err_res; |
| - } |
| - |
| - hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); |
| - if (IS_ERR(hdmi->iahb_clk)) { |
| - ret = PTR_ERR(hdmi->iahb_clk); |
| - dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret); |
| - goto err_isfr; |
| - } |
| - |
| - ret = clk_prepare_enable(hdmi->iahb_clk); |
| - if (ret) { |
| - dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret); |
| - goto err_isfr; |
| - } |
| - |
| - /* Product and revision IDs */ |
| - hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8) |
| - | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0); |
| - prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0); |
| - prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1); |
| - |
| - if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX || |
| - (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) { |
| - dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n", |
| - hdmi->version, prod_id0, prod_id1); |
| - ret = -ENODEV; |
| - goto err_iahb; |
| - } |
| - |
| - ret = dw_hdmi_detect_phy(hdmi); |
| - if (ret < 0) |
| - goto err_iahb; |
| - |
| - dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n", |
| - hdmi->version >> 12, hdmi->version & 0xfff, |
| - prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without", |
| - hdmi->phy.name); |
| - |
| - initialize_hdmi_ih_mutes(hdmi); |
| - |
| - irq = platform_get_irq(pdev, 0); |
| - if (irq < 0) { |
| - ret = irq; |
| - goto err_iahb; |
| - } |
| - |
| - ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq, |
| - dw_hdmi_irq, IRQF_SHARED, |
| - dev_name(dev), hdmi); |
| - if (ret) |
| - goto err_iahb; |
| - |
| - /* |
| - * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator |
| - * N and cts values before enabling phy |
| - */ |
| - hdmi_init_clk_regenerator(hdmi); |
| - |
| - /* If DDC bus is not specified, try to register HDMI I2C bus */ |
| - if (!hdmi->ddc) { |
| - hdmi->ddc = dw_hdmi_i2c_adapter(hdmi); |
| - if (IS_ERR(hdmi->ddc)) |
| - hdmi->ddc = NULL; |
| - } |
| - |
| - /* |
| - * Configure registers related to HDMI interrupt |
| - * generation before registering IRQ. |
| - */ |
| - hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); |
| - |
| - /* Clear Hotplug interrupts */ |
| - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, |
| - HDMI_IH_PHY_STAT0); |
| - |
| - hdmi->bridge.driver_private = hdmi; |
| - hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; |
| -#ifdef CONFIG_OF |
| - hdmi->bridge.of_node = pdev->dev.of_node; |
| -#endif |
| - |
| - ret = dw_hdmi_fb_registered(hdmi); |
| - if (ret) |
| - goto err_iahb; |
| - |
| - /* Unmute interrupts */ |
| - hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), |
| - HDMI_IH_MUTE_PHY_STAT0); |
| - |
| - memset(&pdevinfo, 0, sizeof(pdevinfo)); |
| - pdevinfo.parent = dev; |
| - pdevinfo.id = PLATFORM_DEVID_AUTO; |
| - |
| - config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID); |
| - config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID); |
| - |
| - if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) { |
| - struct dw_hdmi_audio_data audio; |
| - |
| - audio.phys = iores->start; |
| - audio.base = hdmi->regs; |
| - audio.irq = irq; |
| - audio.hdmi = hdmi; |
| - audio.eld = hdmi->connector.eld; |
| - |
| - pdevinfo.name = "dw-hdmi-ahb-audio"; |
| - pdevinfo.data = &audio; |
| - pdevinfo.size_data = sizeof(audio); |
| - pdevinfo.dma_mask = DMA_BIT_MASK(32); |
| - hdmi->audio = platform_device_register_full(&pdevinfo); |
| - } else if (config0 & HDMI_CONFIG0_I2S) { |
| - struct dw_hdmi_i2s_audio_data audio; |
| - |
| - audio.hdmi = hdmi; |
| - audio.write = hdmi_writeb; |
| - audio.read = hdmi_readb; |
| - |
| - pdevinfo.name = "dw-hdmi-i2s-audio"; |
| - pdevinfo.data = &audio; |
| - pdevinfo.size_data = sizeof(audio); |
| - pdevinfo.dma_mask = DMA_BIT_MASK(32); |
| - hdmi->audio = platform_device_register_full(&pdevinfo); |
| - } |
| - |
| - /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */ |
| - if (hdmi->i2c) |
| - dw_hdmi_i2c_init(hdmi); |
| - |
| - platform_set_drvdata(pdev, hdmi); |
| - |
| - return hdmi; |
| - |
| -err_iahb: |
| - if (hdmi->i2c) { |
| - i2c_del_adapter(&hdmi->i2c->adap); |
| - hdmi->ddc = NULL; |
| - } |
| - |
| - clk_disable_unprepare(hdmi->iahb_clk); |
| -err_isfr: |
| - clk_disable_unprepare(hdmi->isfr_clk); |
| -err_res: |
| - i2c_put_adapter(hdmi->ddc); |
| - |
| - return ERR_PTR(ret); |
| -} |
| - |
| -static void __dw_hdmi_remove(struct dw_hdmi *hdmi) |
| -{ |
| - if (hdmi->audio && !IS_ERR(hdmi->audio)) |
| - platform_device_unregister(hdmi->audio); |
| - |
| - /* Disable all interrupts */ |
| - hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); |
| - |
| - clk_disable_unprepare(hdmi->iahb_clk); |
| - clk_disable_unprepare(hdmi->isfr_clk); |
| - |
| - if (hdmi->i2c) |
| - i2c_del_adapter(&hdmi->i2c->adap); |
| - else |
| - i2c_put_adapter(hdmi->ddc); |
| -} |
| - |
| -/* ----------------------------------------------------------------------------- |
| - * Probe/remove API, used from platforms based on the DRM bridge API. |
| - */ |
| -int dw_hdmi_probe(struct platform_device *pdev, |
| - const struct dw_hdmi_plat_data *plat_data) |
| -{ |
| - struct dw_hdmi *hdmi; |
| - int ret; |
| - |
| - hdmi = __dw_hdmi_probe(pdev, plat_data); |
| - if (IS_ERR(hdmi)) |
| - return PTR_ERR(hdmi); |
| - |
| - ret = drm_bridge_add(&hdmi->bridge); |
| - if (ret < 0) { |
| - __dw_hdmi_remove(hdmi); |
| - return ret; |
| - } |
| - |
| - return 0; |
| -} |
| -EXPORT_SYMBOL_GPL(dw_hdmi_probe); |
| - |
| -void dw_hdmi_remove(struct platform_device *pdev) |
| -{ |
| - struct dw_hdmi *hdmi = platform_get_drvdata(pdev); |
| - |
| - drm_bridge_remove(&hdmi->bridge); |
| - |
| - __dw_hdmi_remove(hdmi); |
| -} |
| -EXPORT_SYMBOL_GPL(dw_hdmi_remove); |
| - |
| -/* ----------------------------------------------------------------------------- |
| - * Bind/unbind API, used from platforms based on the component framework. |
| - */ |
| -int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, |
| - const struct dw_hdmi_plat_data *plat_data) |
| -{ |
| - struct dw_hdmi *hdmi; |
| - int ret; |
| - |
| - hdmi = __dw_hdmi_probe(pdev, plat_data); |
| - if (IS_ERR(hdmi)) |
| - return PTR_ERR(hdmi); |
| - |
| - ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); |
| - if (ret) { |
| - dw_hdmi_remove(pdev); |
| - DRM_ERROR("Failed to initialize bridge with drm\n"); |
| - return ret; |
| - } |
| - |
| - return 0; |
| -} |
| -EXPORT_SYMBOL_GPL(dw_hdmi_bind); |
| - |
| -void dw_hdmi_unbind(struct device *dev) |
| -{ |
| - struct dw_hdmi *hdmi = dev_get_drvdata(dev); |
| - |
| - __dw_hdmi_remove(hdmi); |
| -} |
| -EXPORT_SYMBOL_GPL(dw_hdmi_unbind); |
| - |
| -MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); |
| -MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>"); |
| -MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); |
| -MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>"); |
| -MODULE_DESCRIPTION("DW HDMI transmitter driver"); |
| -MODULE_LICENSE("GPL"); |
| -MODULE_ALIAS("platform:dw-hdmi"); |
| --- a/drivers/gpu/drm/bridge/dw-hdmi.h |
| +++ /dev/null |
| @@ -1,1153 +0,0 @@ |
| -/* |
| - * Copyright (C) 2011 Freescale Semiconductor, Inc. |
| - * |
| - * This program is free software; you can redistribute it and/or modify |
| - * it under the terms of the GNU General Public License as published by |
| - * the Free Software Foundation; either version 2 of the License, or |
| - * (at your option) any later version. |
| - */ |
| - |
| -#ifndef __DW_HDMI_H__ |
| -#define __DW_HDMI_H__ |
| - |
| -/* Identification Registers */ |
| -#define HDMI_DESIGN_ID 0x0000 |
| -#define HDMI_REVISION_ID 0x0001 |
| -#define HDMI_PRODUCT_ID0 0x0002 |
| -#define HDMI_PRODUCT_ID1 0x0003 |
| -#define HDMI_CONFIG0_ID 0x0004 |
| -#define HDMI_CONFIG1_ID 0x0005 |
| -#define HDMI_CONFIG2_ID 0x0006 |
| -#define HDMI_CONFIG3_ID 0x0007 |
| - |
| -/* Interrupt Registers */ |
| -#define HDMI_IH_FC_STAT0 0x0100 |
| -#define HDMI_IH_FC_STAT1 0x0101 |
| -#define HDMI_IH_FC_STAT2 0x0102 |
| -#define HDMI_IH_AS_STAT0 0x0103 |
| -#define HDMI_IH_PHY_STAT0 0x0104 |
| -#define HDMI_IH_I2CM_STAT0 0x0105 |
| -#define HDMI_IH_CEC_STAT0 0x0106 |
| -#define HDMI_IH_VP_STAT0 0x0107 |
| -#define HDMI_IH_I2CMPHY_STAT0 0x0108 |
| -#define HDMI_IH_AHBDMAAUD_STAT0 0x0109 |
| - |
| -#define HDMI_IH_MUTE_FC_STAT0 0x0180 |
| -#define HDMI_IH_MUTE_FC_STAT1 0x0181 |
| -#define HDMI_IH_MUTE_FC_STAT2 0x0182 |
| -#define HDMI_IH_MUTE_AS_STAT0 0x0183 |
| -#define HDMI_IH_MUTE_PHY_STAT0 0x0184 |
| -#define HDMI_IH_MUTE_I2CM_STAT0 0x0185 |
| -#define HDMI_IH_MUTE_CEC_STAT0 0x0186 |
| -#define HDMI_IH_MUTE_VP_STAT0 0x0187 |
| -#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188 |
| -#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189 |
| -#define HDMI_IH_MUTE 0x01FF |
| - |
| -/* Video Sample Registers */ |
| -#define HDMI_TX_INVID0 0x0200 |
| -#define HDMI_TX_INSTUFFING 0x0201 |
| -#define HDMI_TX_GYDATA0 0x0202 |
| -#define HDMI_TX_GYDATA1 0x0203 |
| -#define HDMI_TX_RCRDATA0 0x0204 |
| -#define HDMI_TX_RCRDATA1 0x0205 |
| -#define HDMI_TX_BCBDATA0 0x0206 |
| -#define HDMI_TX_BCBDATA1 0x0207 |
| - |
| -/* Video Packetizer Registers */ |
| -#define HDMI_VP_STATUS 0x0800 |
| -#define HDMI_VP_PR_CD 0x0801 |
| -#define HDMI_VP_STUFF 0x0802 |
| -#define HDMI_VP_REMAP 0x0803 |
| -#define HDMI_VP_CONF 0x0804 |
| -#define HDMI_VP_STAT 0x0805 |
| -#define HDMI_VP_INT 0x0806 |
| -#define HDMI_VP_MASK 0x0807 |
| -#define HDMI_VP_POL 0x0808 |
| - |
| -/* Frame Composer Registers */ |
| -#define HDMI_FC_INVIDCONF 0x1000 |
| -#define HDMI_FC_INHACTV0 0x1001 |
| -#define HDMI_FC_INHACTV1 0x1002 |
| -#define HDMI_FC_INHBLANK0 0x1003 |
| -#define HDMI_FC_INHBLANK1 0x1004 |
| -#define HDMI_FC_INVACTV0 0x1005 |
| -#define HDMI_FC_INVACTV1 0x1006 |
| -#define HDMI_FC_INVBLANK 0x1007 |
| -#define HDMI_FC_HSYNCINDELAY0 0x1008 |
| -#define HDMI_FC_HSYNCINDELAY1 0x1009 |
| -#define HDMI_FC_HSYNCINWIDTH0 0x100A |
| -#define HDMI_FC_HSYNCINWIDTH1 0x100B |
| -#define HDMI_FC_VSYNCINDELAY 0x100C |
| -#define HDMI_FC_VSYNCINWIDTH 0x100D |
| -#define HDMI_FC_INFREQ0 0x100E |
| -#define HDMI_FC_INFREQ1 0x100F |
| -#define HDMI_FC_INFREQ2 0x1010 |
| -#define HDMI_FC_CTRLDUR 0x1011 |
| -#define HDMI_FC_EXCTRLDUR 0x1012 |
| -#define HDMI_FC_EXCTRLSPAC 0x1013 |
| -#define HDMI_FC_CH0PREAM 0x1014 |
| -#define HDMI_FC_CH1PREAM 0x1015 |
| -#define HDMI_FC_CH2PREAM 0x1016 |
| -#define HDMI_FC_AVICONF3 0x1017 |
| -#define HDMI_FC_GCP 0x1018 |
| -#define HDMI_FC_AVICONF0 0x1019 |
| -#define HDMI_FC_AVICONF1 0x101A |
| -#define HDMI_FC_AVICONF2 0x101B |
| -#define HDMI_FC_AVIVID 0x101C |
| -#define HDMI_FC_AVIETB0 0x101D |
| -#define HDMI_FC_AVIETB1 0x101E |
| -#define HDMI_FC_AVISBB0 0x101F |
| -#define HDMI_FC_AVISBB1 0x1020 |
| -#define HDMI_FC_AVIELB0 0x1021 |
| -#define HDMI_FC_AVIELB1 0x1022 |
| -#define HDMI_FC_AVISRB0 0x1023 |
| -#define HDMI_FC_AVISRB1 0x1024 |
| -#define HDMI_FC_AUDICONF0 0x1025 |
| -#define HDMI_FC_AUDICONF1 0x1026 |
| -#define HDMI_FC_AUDICONF2 0x1027 |
| -#define HDMI_FC_AUDICONF3 0x1028 |
| -#define HDMI_FC_VSDIEEEID0 0x1029 |
| -#define HDMI_FC_VSDSIZE 0x102A |
| -#define HDMI_FC_VSDIEEEID1 0x1030 |
| -#define HDMI_FC_VSDIEEEID2 0x1031 |
| -#define HDMI_FC_VSDPAYLOAD0 0x1032 |
| -#define HDMI_FC_VSDPAYLOAD1 0x1033 |
| -#define HDMI_FC_VSDPAYLOAD2 0x1034 |
| -#define HDMI_FC_VSDPAYLOAD3 0x1035 |
| -#define HDMI_FC_VSDPAYLOAD4 0x1036 |
| -#define HDMI_FC_VSDPAYLOAD5 0x1037 |
| -#define HDMI_FC_VSDPAYLOAD6 0x1038 |
| -#define HDMI_FC_VSDPAYLOAD7 0x1039 |
| -#define HDMI_FC_VSDPAYLOAD8 0x103A |
| -#define HDMI_FC_VSDPAYLOAD9 0x103B |
| -#define HDMI_FC_VSDPAYLOAD10 0x103C |
| -#define HDMI_FC_VSDPAYLOAD11 0x103D |
| -#define HDMI_FC_VSDPAYLOAD12 0x103E |
| -#define HDMI_FC_VSDPAYLOAD13 0x103F |
| -#define HDMI_FC_VSDPAYLOAD14 0x1040 |
| -#define HDMI_FC_VSDPAYLOAD15 0x1041 |
| -#define HDMI_FC_VSDPAYLOAD16 0x1042 |
| -#define HDMI_FC_VSDPAYLOAD17 0x1043 |
| -#define HDMI_FC_VSDPAYLOAD18 0x1044 |
| -#define HDMI_FC_VSDPAYLOAD19 0x1045 |
| -#define HDMI_FC_VSDPAYLOAD20 0x1046 |
| -#define HDMI_FC_VSDPAYLOAD21 0x1047 |
| -#define HDMI_FC_VSDPAYLOAD22 0x1048 |
| -#define HDMI_FC_VSDPAYLOAD23 0x1049 |
| -#define HDMI_FC_SPDVENDORNAME0 0x104A |
| -#define HDMI_FC_SPDVENDORNAME1 0x104B |
| -#define HDMI_FC_SPDVENDORNAME2 0x104C |
| -#define HDMI_FC_SPDVENDORNAME3 0x104D |
| -#define HDMI_FC_SPDVENDORNAME4 0x104E |
| -#define HDMI_FC_SPDVENDORNAME5 0x104F |
| -#define HDMI_FC_SPDVENDORNAME6 0x1050 |
| -#define HDMI_FC_SPDVENDORNAME7 0x1051 |
| -#define HDMI_FC_SDPPRODUCTNAME0 0x1052 |
| -#define HDMI_FC_SDPPRODUCTNAME1 0x1053 |
| -#define HDMI_FC_SDPPRODUCTNAME2 0x1054 |
| -#define HDMI_FC_SDPPRODUCTNAME3 0x1055 |
| -#define HDMI_FC_SDPPRODUCTNAME4 0x1056 |
| -#define HDMI_FC_SDPPRODUCTNAME5 0x1057 |
| -#define HDMI_FC_SDPPRODUCTNAME6 0x1058 |
| -#define HDMI_FC_SDPPRODUCTNAME7 0x1059 |
| -#define HDMI_FC_SDPPRODUCTNAME8 0x105A |
| -#define HDMI_FC_SDPPRODUCTNAME9 0x105B |
| -#define HDMI_FC_SDPPRODUCTNAME10 0x105C |
| -#define HDMI_FC_SDPPRODUCTNAME11 0x105D |
| -#define HDMI_FC_SDPPRODUCTNAME12 0x105E |
| -#define HDMI_FC_SDPPRODUCTNAME13 0x105F |
| -#define HDMI_FC_SDPPRODUCTNAME14 0x1060 |
| -#define HDMI_FC_SPDPRODUCTNAME15 0x1061 |
| -#define HDMI_FC_SPDDEVICEINF 0x1062 |
| -#define HDMI_FC_AUDSCONF 0x1063 |
| -#define HDMI_FC_AUDSSTAT 0x1064 |
| -#define HDMI_FC_DATACH0FILL 0x1070 |
| -#define HDMI_FC_DATACH1FILL 0x1071 |
| -#define HDMI_FC_DATACH2FILL 0x1072 |
| -#define HDMI_FC_CTRLQHIGH 0x1073 |
| -#define HDMI_FC_CTRLQLOW 0x1074 |
| -#define HDMI_FC_ACP0 0x1075 |
| -#define HDMI_FC_ACP28 0x1076 |
| -#define HDMI_FC_ACP27 0x1077 |
| -#define HDMI_FC_ACP26 0x1078 |
| -#define HDMI_FC_ACP25 0x1079 |
| -#define HDMI_FC_ACP24 0x107A |
| -#define HDMI_FC_ACP23 0x107B |
| -#define HDMI_FC_ACP22 0x107C |
| -#define HDMI_FC_ACP21 0x107D |
| -#define HDMI_FC_ACP20 0x107E |
| -#define HDMI_FC_ACP19 0x107F |
| -#define HDMI_FC_ACP18 0x1080 |
| -#define HDMI_FC_ACP17 0x1081 |
| -#define HDMI_FC_ACP16 0x1082 |
| -#define HDMI_FC_ACP15 0x1083 |
| -#define HDMI_FC_ACP14 0x1084 |
| -#define HDMI_FC_ACP13 0x1085 |
| -#define HDMI_FC_ACP12 0x1086 |
| -#define HDMI_FC_ACP11 0x1087 |
| -#define HDMI_FC_ACP10 0x1088 |
| -#define HDMI_FC_ACP9 0x1089 |
| -#define HDMI_FC_ACP8 0x108A |
| -#define HDMI_FC_ACP7 0x108B |
| -#define HDMI_FC_ACP6 0x108C |
| -#define HDMI_FC_ACP5 0x108D |
| -#define HDMI_FC_ACP4 0x108E |
| -#define HDMI_FC_ACP3 0x108F |
| -#define HDMI_FC_ACP2 0x1090 |
| -#define HDMI_FC_ACP1 0x1091 |
| -#define HDMI_FC_ISCR1_0 0x1092 |
| -#define HDMI_FC_ISCR1_16 0x1093 |
| -#define HDMI_FC_ISCR1_15 0x1094 |
| -#define HDMI_FC_ISCR1_14 0x1095 |
| -#define HDMI_FC_ISCR1_13 0x1096 |
| -#define HDMI_FC_ISCR1_12 0x1097 |
| -#define HDMI_FC_ISCR1_11 0x1098 |
| -#define HDMI_FC_ISCR1_10 0x1099 |
| -#define HDMI_FC_ISCR1_9 0x109A |
| -#define HDMI_FC_ISCR1_8 0x109B |
| -#define HDMI_FC_ISCR1_7 0x109C |
| -#define HDMI_FC_ISCR1_6 0x109D |
| -#define HDMI_FC_ISCR1_5 0x109E |
| -#define HDMI_FC_ISCR1_4 0x109F |
| -#define HDMI_FC_ISCR1_3 0x10A0 |
| -#define HDMI_FC_ISCR1_2 0x10A1 |
| -#define HDMI_FC_ISCR1_1 0x10A2 |
| -#define HDMI_FC_ISCR2_15 0x10A3 |
| -#define HDMI_FC_ISCR2_14 0x10A4 |
| -#define HDMI_FC_ISCR2_13 0x10A5 |
| -#define HDMI_FC_ISCR2_12 0x10A6 |
| -#define HDMI_FC_ISCR2_11 0x10A7 |
| -#define HDMI_FC_ISCR2_10 0x10A8 |
| -#define HDMI_FC_ISCR2_9 0x10A9 |
| -#define HDMI_FC_ISCR2_8 0x10AA |
| -#define HDMI_FC_ISCR2_7 0x10AB |
| -#define HDMI_FC_ISCR2_6 0x10AC |
| -#define HDMI_FC_ISCR2_5 0x10AD |
| -#define HDMI_FC_ISCR2_4 0x10AE |
| -#define HDMI_FC_ISCR2_3 0x10AF |
| -#define HDMI_FC_ISCR2_2 0x10B0 |
| -#define HDMI_FC_ISCR2_1 0x10B1 |
| -#define HDMI_FC_ISCR2_0 0x10B2 |
| -#define HDMI_FC_DATAUTO0 0x10B3 |
| -#define HDMI_FC_DATAUTO1 0x10B4 |
| -#define HDMI_FC_DATAUTO2 0x10B5 |
| -#define HDMI_FC_DATMAN 0x10B6 |
| -#define HDMI_FC_DATAUTO3 0x10B7 |
| -#define HDMI_FC_RDRB0 0x10B8 |
| -#define HDMI_FC_RDRB1 0x10B9 |
| -#define HDMI_FC_RDRB2 0x10BA |
| -#define HDMI_FC_RDRB3 0x10BB |
| -#define HDMI_FC_RDRB4 0x10BC |
| -#define HDMI_FC_RDRB5 0x10BD |
| -#define HDMI_FC_RDRB6 0x10BE |
| -#define HDMI_FC_RDRB7 0x10BF |
| -#define HDMI_FC_STAT0 0x10D0 |
| -#define HDMI_FC_INT0 0x10D1 |
| -#define HDMI_FC_MASK0 0x10D2 |
| -#define HDMI_FC_POL0 0x10D3 |
| -#define HDMI_FC_STAT1 0x10D4 |
| -#define HDMI_FC_INT1 0x10D5 |
| -#define HDMI_FC_MASK1 0x10D6 |
| -#define HDMI_FC_POL1 0x10D7 |
| -#define HDMI_FC_STAT2 0x10D8 |
| -#define HDMI_FC_INT2 0x10D9 |
| -#define HDMI_FC_MASK2 0x10DA |
| -#define HDMI_FC_POL2 0x10DB |
| -#define HDMI_FC_PRCONF 0x10E0 |
| - |
| -#define HDMI_FC_GMD_STAT 0x1100 |
| -#define HDMI_FC_GMD_EN 0x1101 |
| -#define HDMI_FC_GMD_UP 0x1102 |
| -#define HDMI_FC_GMD_CONF 0x1103 |
| -#define HDMI_FC_GMD_HB 0x1104 |
| -#define HDMI_FC_GMD_PB0 0x1105 |
| -#define HDMI_FC_GMD_PB1 0x1106 |
| -#define HDMI_FC_GMD_PB2 0x1107 |
| -#define HDMI_FC_GMD_PB3 0x1108 |
| -#define HDMI_FC_GMD_PB4 0x1109 |
| -#define HDMI_FC_GMD_PB5 0x110A |
| -#define HDMI_FC_GMD_PB6 0x110B |
| -#define HDMI_FC_GMD_PB7 0x110C |
| -#define HDMI_FC_GMD_PB8 0x110D |
| -#define HDMI_FC_GMD_PB9 0x110E |
| -#define HDMI_FC_GMD_PB10 0x110F |
| -#define HDMI_FC_GMD_PB11 0x1110 |
| -#define HDMI_FC_GMD_PB12 0x1111 |
| -#define HDMI_FC_GMD_PB13 0x1112 |
| -#define HDMI_FC_GMD_PB14 0x1113 |
| -#define HDMI_FC_GMD_PB15 0x1114 |
| -#define HDMI_FC_GMD_PB16 0x1115 |
| -#define HDMI_FC_GMD_PB17 0x1116 |
| -#define HDMI_FC_GMD_PB18 0x1117 |
| -#define HDMI_FC_GMD_PB19 0x1118 |
| -#define HDMI_FC_GMD_PB20 0x1119 |
| -#define HDMI_FC_GMD_PB21 0x111A |
| -#define HDMI_FC_GMD_PB22 0x111B |
| -#define HDMI_FC_GMD_PB23 0x111C |
| -#define HDMI_FC_GMD_PB24 0x111D |
| -#define HDMI_FC_GMD_PB25 0x111E |
| -#define HDMI_FC_GMD_PB26 0x111F |
| -#define HDMI_FC_GMD_PB27 0x1120 |
| - |
| -#define HDMI_FC_DBGFORCE 0x1200 |
| -#define HDMI_FC_DBGAUD0CH0 0x1201 |
| -#define HDMI_FC_DBGAUD1CH0 0x1202 |
| -#define HDMI_FC_DBGAUD2CH0 0x1203 |
| -#define HDMI_FC_DBGAUD0CH1 0x1204 |
| -#define HDMI_FC_DBGAUD1CH1 0x1205 |
| -#define HDMI_FC_DBGAUD2CH1 0x1206 |
| -#define HDMI_FC_DBGAUD0CH2 0x1207 |
| -#define HDMI_FC_DBGAUD1CH2 0x1208 |
| -#define HDMI_FC_DBGAUD2CH2 0x1209 |
| -#define HDMI_FC_DBGAUD0CH3 0x120A |
| -#define HDMI_FC_DBGAUD1CH3 0x120B |
| -#define HDMI_FC_DBGAUD2CH3 0x120C |
| -#define HDMI_FC_DBGAUD0CH4 0x120D |
| -#define HDMI_FC_DBGAUD1CH4 0x120E |
| -#define HDMI_FC_DBGAUD2CH4 0x120F |
| -#define HDMI_FC_DBGAUD0CH5 0x1210 |
| -#define HDMI_FC_DBGAUD1CH5 0x1211 |
| -#define HDMI_FC_DBGAUD2CH5 0x1212 |
| -#define HDMI_FC_DBGAUD0CH6 0x1213 |
| -#define HDMI_FC_DBGAUD1CH6 0x1214 |
| -#define HDMI_FC_DBGAUD2CH6 0x1215 |
| -#define HDMI_FC_DBGAUD0CH7 0x1216 |
| -#define HDMI_FC_DBGAUD1CH7 0x1217 |
| -#define HDMI_FC_DBGAUD2CH7 0x1218 |
| -#define HDMI_FC_DBGTMDS0 0x1219 |
| -#define HDMI_FC_DBGTMDS1 0x121A |
| -#define HDMI_FC_DBGTMDS2 0x121B |
| - |
| -/* HDMI Source PHY Registers */ |
| -#define HDMI_PHY_CONF0 0x3000 |
| -#define HDMI_PHY_TST0 0x3001 |
| -#define HDMI_PHY_TST1 0x3002 |
| -#define HDMI_PHY_TST2 0x3003 |
| -#define HDMI_PHY_STAT0 0x3004 |
| -#define HDMI_PHY_INT0 0x3005 |
| -#define HDMI_PHY_MASK0 0x3006 |
| -#define HDMI_PHY_POL0 0x3007 |
| - |
| -/* HDMI Master PHY Registers */ |
| -#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020 |
| -#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021 |
| -#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022 |
| -#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023 |
| -#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024 |
| -#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025 |
| -#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026 |
| -#define HDMI_PHY_I2CM_INT_ADDR 0x3027 |
| -#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028 |
| -#define HDMI_PHY_I2CM_DIV_ADDR 0x3029 |
| -#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a |
| -#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b |
| -#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c |
| -#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d |
| -#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e |
| -#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f |
| -#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030 |
| -#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031 |
| -#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032 |
| - |
| -/* Audio Sampler Registers */ |
| -#define HDMI_AUD_CONF0 0x3100 |
| -#define HDMI_AUD_CONF1 0x3101 |
| -#define HDMI_AUD_INT 0x3102 |
| -#define HDMI_AUD_CONF2 0x3103 |
| -#define HDMI_AUD_N1 0x3200 |
| -#define HDMI_AUD_N2 0x3201 |
| -#define HDMI_AUD_N3 0x3202 |
| -#define HDMI_AUD_CTS1 0x3203 |
| -#define HDMI_AUD_CTS2 0x3204 |
| -#define HDMI_AUD_CTS3 0x3205 |
| -#define HDMI_AUD_INPUTCLKFS 0x3206 |
| -#define HDMI_AUD_SPDIFINT 0x3302 |
| -#define HDMI_AUD_CONF0_HBR 0x3400 |
| -#define HDMI_AUD_HBR_STATUS 0x3401 |
| -#define HDMI_AUD_HBR_INT 0x3402 |
| -#define HDMI_AUD_HBR_POL 0x3403 |
| -#define HDMI_AUD_HBR_MASK 0x3404 |
| - |
| -/* |
| - * Generic Parallel Audio Interface Registers |
| - * Not used as GPAUD interface is not enabled in hw |
| - */ |
| -#define HDMI_GP_CONF0 0x3500 |
| -#define HDMI_GP_CONF1 0x3501 |
| -#define HDMI_GP_CONF2 0x3502 |
| -#define HDMI_GP_STAT 0x3503 |
| -#define HDMI_GP_INT 0x3504 |
| -#define HDMI_GP_MASK 0x3505 |
| -#define HDMI_GP_POL 0x3506 |
| - |
| -/* Audio DMA Registers */ |
| -#define HDMI_AHB_DMA_CONF0 0x3600 |
| -#define HDMI_AHB_DMA_START 0x3601 |
| -#define HDMI_AHB_DMA_STOP 0x3602 |
| -#define HDMI_AHB_DMA_THRSLD 0x3603 |
| -#define HDMI_AHB_DMA_STRADDR0 0x3604 |
| -#define HDMI_AHB_DMA_STRADDR1 0x3605 |
| -#define HDMI_AHB_DMA_STRADDR2 0x3606 |
| -#define HDMI_AHB_DMA_STRADDR3 0x3607 |
| -#define HDMI_AHB_DMA_STPADDR0 0x3608 |
| -#define HDMI_AHB_DMA_STPADDR1 0x3609 |
| -#define HDMI_AHB_DMA_STPADDR2 0x360a |
| -#define HDMI_AHB_DMA_STPADDR3 0x360b |
| -#define HDMI_AHB_DMA_BSTADDR0 0x360c |
| -#define HDMI_AHB_DMA_BSTADDR1 0x360d |
| -#define HDMI_AHB_DMA_BSTADDR2 0x360e |
| -#define HDMI_AHB_DMA_BSTADDR3 0x360f |
| -#define HDMI_AHB_DMA_MBLENGTH0 0x3610 |
| -#define HDMI_AHB_DMA_MBLENGTH1 0x3611 |
| -#define HDMI_AHB_DMA_STAT 0x3612 |
| -#define HDMI_AHB_DMA_INT 0x3613 |
| -#define HDMI_AHB_DMA_MASK 0x3614 |
| -#define HDMI_AHB_DMA_POL 0x3615 |
| -#define HDMI_AHB_DMA_CONF1 0x3616 |
| -#define HDMI_AHB_DMA_BUFFSTAT 0x3617 |
| -#define HDMI_AHB_DMA_BUFFINT 0x3618 |
| -#define HDMI_AHB_DMA_BUFFMASK 0x3619 |
| -#define HDMI_AHB_DMA_BUFFPOL 0x361a |
| - |
| -/* Main Controller Registers */ |
| -#define HDMI_MC_SFRDIV 0x4000 |
| -#define HDMI_MC_CLKDIS 0x4001 |
| -#define HDMI_MC_SWRSTZ 0x4002 |
| -#define HDMI_MC_OPCTRL 0x4003 |
| -#define HDMI_MC_FLOWCTRL 0x4004 |
| -#define HDMI_MC_PHYRSTZ 0x4005 |
| -#define HDMI_MC_LOCKONCLOCK 0x4006 |
| -#define HDMI_MC_HEACPHY_RST 0x4007 |
| - |
| -/* Color Space Converter Registers */ |
| -#define HDMI_CSC_CFG 0x4100 |
| -#define HDMI_CSC_SCALE 0x4101 |
| -#define HDMI_CSC_COEF_A1_MSB 0x4102 |
| -#define HDMI_CSC_COEF_A1_LSB 0x4103 |
| -#define HDMI_CSC_COEF_A2_MSB 0x4104 |
| -#define HDMI_CSC_COEF_A2_LSB 0x4105 |
| -#define HDMI_CSC_COEF_A3_MSB 0x4106 |
| -#define HDMI_CSC_COEF_A3_LSB 0x4107 |
| -#define HDMI_CSC_COEF_A4_MSB 0x4108 |
| -#define HDMI_CSC_COEF_A4_LSB 0x4109 |
| -#define HDMI_CSC_COEF_B1_MSB 0x410A |
| -#define HDMI_CSC_COEF_B1_LSB 0x410B |
| -#define HDMI_CSC_COEF_B2_MSB 0x410C |
| -#define HDMI_CSC_COEF_B2_LSB 0x410D |
| -#define HDMI_CSC_COEF_B3_MSB 0x410E |
| -#define HDMI_CSC_COEF_B3_LSB 0x410F |
| -#define HDMI_CSC_COEF_B4_MSB 0x4110 |
| -#define HDMI_CSC_COEF_B4_LSB 0x4111 |
| -#define HDMI_CSC_COEF_C1_MSB 0x4112 |
| -#define HDMI_CSC_COEF_C1_LSB 0x4113 |
| -#define HDMI_CSC_COEF_C2_MSB 0x4114 |
| -#define HDMI_CSC_COEF_C2_LSB 0x4115 |
| -#define HDMI_CSC_COEF_C3_MSB 0x4116 |
| -#define HDMI_CSC_COEF_C3_LSB 0x4117 |
| -#define HDMI_CSC_COEF_C4_MSB 0x4118 |
| -#define HDMI_CSC_COEF_C4_LSB 0x4119 |
| - |
| -/* HDCP Encryption Engine Registers */ |
| -#define HDMI_A_HDCPCFG0 0x5000 |
| -#define HDMI_A_HDCPCFG1 0x5001 |
| -#define HDMI_A_HDCPOBS0 0x5002 |
| -#define HDMI_A_HDCPOBS1 0x5003 |
| -#define HDMI_A_HDCPOBS2 0x5004 |
| -#define HDMI_A_HDCPOBS3 0x5005 |
| -#define HDMI_A_APIINTCLR 0x5006 |
| -#define HDMI_A_APIINTSTAT 0x5007 |
| -#define HDMI_A_APIINTMSK 0x5008 |
| -#define HDMI_A_VIDPOLCFG 0x5009 |
| -#define HDMI_A_OESSWCFG 0x500A |
| -#define HDMI_A_TIMER1SETUP0 0x500B |
| -#define HDMI_A_TIMER1SETUP1 0x500C |
| -#define HDMI_A_TIMER2SETUP0 0x500D |
| -#define HDMI_A_TIMER2SETUP1 0x500E |
| -#define HDMI_A_100MSCFG 0x500F |
| -#define HDMI_A_2SCFG0 0x5010 |
| -#define HDMI_A_2SCFG1 0x5011 |
| -#define HDMI_A_5SCFG0 0x5012 |
| -#define HDMI_A_5SCFG1 0x5013 |
| -#define HDMI_A_SRMVERLSB 0x5014 |
| -#define HDMI_A_SRMVERMSB 0x5015 |
| -#define HDMI_A_SRMCTRL 0x5016 |
| -#define HDMI_A_SFRSETUP 0x5017 |
| -#define HDMI_A_I2CHSETUP 0x5018 |
| -#define HDMI_A_INTSETUP 0x5019 |
| -#define HDMI_A_PRESETUP 0x501A |
| -#define HDMI_A_SRM_BASE 0x5020 |
| - |
| -/* CEC Engine Registers */ |
| -#define HDMI_CEC_CTRL 0x7D00 |
| -#define HDMI_CEC_STAT 0x7D01 |
| -#define HDMI_CEC_MASK 0x7D02 |
| -#define HDMI_CEC_POLARITY 0x7D03 |
| -#define HDMI_CEC_INT 0x7D04 |
| -#define HDMI_CEC_ADDR_L 0x7D05 |
| -#define HDMI_CEC_ADDR_H 0x7D06 |
| -#define HDMI_CEC_TX_CNT 0x7D07 |
| -#define HDMI_CEC_RX_CNT 0x7D08 |
| -#define HDMI_CEC_TX_DATA0 0x7D10 |
| -#define HDMI_CEC_TX_DATA1 0x7D11 |
| -#define HDMI_CEC_TX_DATA2 0x7D12 |
| -#define HDMI_CEC_TX_DATA3 0x7D13 |
| -#define HDMI_CEC_TX_DATA4 0x7D14 |
| -#define HDMI_CEC_TX_DATA5 0x7D15 |
| -#define HDMI_CEC_TX_DATA6 0x7D16 |
| -#define HDMI_CEC_TX_DATA7 0x7D17 |
| -#define HDMI_CEC_TX_DATA8 0x7D18 |
| -#define HDMI_CEC_TX_DATA9 0x7D19 |
| -#define HDMI_CEC_TX_DATA10 0x7D1a |
| -#define HDMI_CEC_TX_DATA11 0x7D1b |
| -#define HDMI_CEC_TX_DATA12 0x7D1c |
| -#define HDMI_CEC_TX_DATA13 0x7D1d |
| -#define HDMI_CEC_TX_DATA14 0x7D1e |
| -#define HDMI_CEC_TX_DATA15 0x7D1f |
| -#define HDMI_CEC_RX_DATA0 0x7D20 |
| -#define HDMI_CEC_RX_DATA1 0x7D21 |
| -#define HDMI_CEC_RX_DATA2 0x7D22 |
| -#define HDMI_CEC_RX_DATA3 0x7D23 |
| -#define HDMI_CEC_RX_DATA4 0x7D24 |
| -#define HDMI_CEC_RX_DATA5 0x7D25 |
| -#define HDMI_CEC_RX_DATA6 0x7D26 |
| -#define HDMI_CEC_RX_DATA7 0x7D27 |
| -#define HDMI_CEC_RX_DATA8 0x7D28 |
| -#define HDMI_CEC_RX_DATA9 0x7D29 |
| -#define HDMI_CEC_RX_DATA10 0x7D2a |
| -#define HDMI_CEC_RX_DATA11 0x7D2b |
| -#define HDMI_CEC_RX_DATA12 0x7D2c |
| -#define HDMI_CEC_RX_DATA13 0x7D2d |
| -#define HDMI_CEC_RX_DATA14 0x7D2e |
| -#define HDMI_CEC_RX_DATA15 0x7D2f |
| -#define HDMI_CEC_LOCK 0x7D30 |
| -#define HDMI_CEC_WKUPCTRL 0x7D31 |
| - |
| -/* I2C Master Registers (E-DDC) */ |
| -#define HDMI_I2CM_SLAVE 0x7E00 |
| -#define HDMI_I2CM_ADDRESS 0x7E01 |
| -#define HDMI_I2CM_DATAO 0x7E02 |
| -#define HDMI_I2CM_DATAI 0x7E03 |
| -#define HDMI_I2CM_OPERATION 0x7E04 |
| -#define HDMI_I2CM_INT 0x7E05 |
| -#define HDMI_I2CM_CTLINT 0x7E06 |
| -#define HDMI_I2CM_DIV 0x7E07 |
| -#define HDMI_I2CM_SEGADDR 0x7E08 |
| -#define HDMI_I2CM_SOFTRSTZ 0x7E09 |
| -#define HDMI_I2CM_SEGPTR 0x7E0A |
| -#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B |
| -#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C |
| -#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D |
| -#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E |
| -#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F |
| -#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10 |
| -#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11 |
| -#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12 |
| - |
| -enum { |
| -/* PRODUCT_ID0 field values */ |
| - HDMI_PRODUCT_ID0_HDMI_TX = 0xa0, |
| - |
| -/* PRODUCT_ID1 field values */ |
| - HDMI_PRODUCT_ID1_HDCP = 0xc0, |
| - HDMI_PRODUCT_ID1_HDMI_RX = 0x02, |
| - HDMI_PRODUCT_ID1_HDMI_TX = 0x01, |
| - |
| -/* CONFIG0_ID field values */ |
| - HDMI_CONFIG0_I2S = 0x10, |
| - |
| -/* CONFIG1_ID field values */ |
| - HDMI_CONFIG1_AHB = 0x01, |
| - |
| -/* CONFIG3_ID field values */ |
| - HDMI_CONFIG3_AHBAUDDMA = 0x02, |
| - HDMI_CONFIG3_GPAUD = 0x01, |
| - |
| -/* IH_FC_INT2 field values */ |
| - HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03, |
| - HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| - HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| - |
| -/* IH_FC_STAT2 field values */ |
| - HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03, |
| - HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| - HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| - |
| -/* IH_PHY_STAT0 field values */ |
| - HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20, |
| - HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10, |
| - HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8, |
| - HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4, |
| - HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2, |
| - HDMI_IH_PHY_STAT0_HPD = 0x1, |
| - |
| -/* IH_I2CM_STAT0 and IH_MUTE_I2CM_STAT0 field values */ |
| - HDMI_IH_I2CM_STAT0_DONE = 0x2, |
| - HDMI_IH_I2CM_STAT0_ERROR = 0x1, |
| - |
| -/* IH_MUTE_I2CMPHY_STAT0 field values */ |
| - HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2, |
| - HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1, |
| - |
| -/* IH_AHBDMAAUD_STAT0 field values */ |
| - HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20, |
| - HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10, |
| - HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08, |
| - HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04, |
| - HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02, |
| - HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01, |
| - |
| -/* IH_MUTE_FC_STAT2 field values */ |
| - HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03, |
| - HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| - HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| - |
| -/* IH_MUTE_AHBDMAAUD_STAT0 field values */ |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20, |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10, |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08, |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04, |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02, |
| - HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01, |
| - |
| -/* IH_MUTE field values */ |
| - HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2, |
| - HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1, |
| - |
| -/* TX_INVID0 field values */ |
| - HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80, |
| - HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80, |
| - HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00, |
| - HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F, |
| - HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0, |
| - |
| -/* TX_INSTUFFING field values */ |
| - HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4, |
| - HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4, |
| - HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0, |
| - HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2, |
| - HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2, |
| - HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0, |
| - HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1, |
| - HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1, |
| - HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0, |
| - |
| -/* VP_PR_CD field values */ |
| - HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0, |
| - HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4, |
| - HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F, |
| - HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0, |
| - |
| -/* VP_STUFF field values */ |
| - HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20, |
| - HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5, |
| - HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10, |
| - HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4, |
| - HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8, |
| - HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3, |
| - HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4, |
| - HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4, |
| - HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0, |
| - HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2, |
| - HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2, |
| - HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0, |
| - HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1, |
| - HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1, |
| - HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0, |
| - |
| -/* VP_CONF field values */ |
| - HDMI_VP_CONF_BYPASS_EN_MASK = 0x40, |
| - HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40, |
| - HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00, |
| - HDMI_VP_CONF_PP_EN_ENMASK = 0x20, |
| - HDMI_VP_CONF_PP_EN_ENABLE = 0x20, |
| - HDMI_VP_CONF_PP_EN_DISABLE = 0x00, |
| - HDMI_VP_CONF_PR_EN_MASK = 0x10, |
| - HDMI_VP_CONF_PR_EN_ENABLE = 0x10, |
| - HDMI_VP_CONF_PR_EN_DISABLE = 0x00, |
| - HDMI_VP_CONF_YCC422_EN_MASK = 0x8, |
| - HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8, |
| - HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0, |
| - HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4, |
| - HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4, |
| - HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0, |
| - HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3, |
| - HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3, |
| - HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1, |
| - HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0, |
| - |
| -/* VP_REMAP field values */ |
| - HDMI_VP_REMAP_MASK = 0x3, |
| - HDMI_VP_REMAP_YCC422_24bit = 0x2, |
| - HDMI_VP_REMAP_YCC422_20bit = 0x1, |
| - HDMI_VP_REMAP_YCC422_16bit = 0x0, |
| - |
| -/* FC_INVIDCONF field values */ |
| - HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80, |
| - HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80, |
| - HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00, |
| - HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40, |
| - HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40, |
| - HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00, |
| - HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20, |
| - HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20, |
| - HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00, |
| - HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10, |
| - HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10, |
| - HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00, |
| - HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8, |
| - HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8, |
| - HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0, |
| - HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2, |
| - HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2, |
| - HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0, |
| - HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1, |
| - HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1, |
| - HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0, |
| - |
| -/* FC_AUDICONF0 field values */ |
| - HDMI_FC_AUDICONF0_CC_OFFSET = 4, |
| - HDMI_FC_AUDICONF0_CC_MASK = 0x70, |
| - HDMI_FC_AUDICONF0_CT_OFFSET = 0, |
| - HDMI_FC_AUDICONF0_CT_MASK = 0xF, |
| - |
| -/* FC_AUDICONF1 field values */ |
| - HDMI_FC_AUDICONF1_SS_OFFSET = 3, |
| - HDMI_FC_AUDICONF1_SS_MASK = 0x18, |
| - HDMI_FC_AUDICONF1_SF_OFFSET = 0, |
| - HDMI_FC_AUDICONF1_SF_MASK = 0x7, |
| - |
| -/* FC_AUDICONF3 field values */ |
| - HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5, |
| - HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60, |
| - HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4, |
| - HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10, |
| - HDMI_FC_AUDICONF3_LSV_OFFSET = 0, |
| - HDMI_FC_AUDICONF3_LSV_MASK = 0xF, |
| - |
| -/* FC_AUDSCHNLS0 field values */ |
| - HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4, |
| - HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30, |
| - HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0, |
| - HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01, |
| - |
| -/* FC_AUDSCHNLS3-6 field values */ |
| - HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0, |
| - HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f, |
| - HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4, |
| - HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0, |
| - HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0, |
| - HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f, |
| - HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4, |
| - HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0, |
| - |
| - HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0, |
| - HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f, |
| - HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4, |
| - HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0, |
| - HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0, |
| - HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f, |
| - HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4, |
| - HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0, |
| - |
| -/* HDMI_FC_AUDSCHNLS7 field values */ |
| - HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4, |
| - HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30, |
| - |
| -/* HDMI_FC_AUDSCHNLS8 field values */ |
| - HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0, |
| - HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4, |
| - HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f, |
| - HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0, |
| - |
| -/* FC_AUDSCONF field values */ |
| - HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0, |
| - HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4, |
| - HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1, |
| - HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0, |
| - HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1, |
| - HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0, |
| - |
| -/* FC_STAT2 field values */ |
| - HDMI_FC_STAT2_OVERFLOW_MASK = 0x03, |
| - HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| - HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| - |
| -/* FC_INT2 field values */ |
| - HDMI_FC_INT2_OVERFLOW_MASK = 0x03, |
| - HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| - HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| - |
| -/* FC_MASK2 field values */ |
| - HDMI_FC_MASK2_OVERFLOW_MASK = 0x03, |
| - HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02, |
| - HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| - |
| -/* FC_PRCONF field values */ |
| - HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0, |
| - HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4, |
| - HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F, |
| - HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0, |
| - |
| -/* FC_AVICONF0-FC_AVICONF3 field values */ |
| - HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03, |
| - HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00, |
| - HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01, |
| - HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02, |
| - HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40, |
| - HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40, |
| - HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00, |
| - HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C, |
| - HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00, |
| - HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04, |
| - HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08, |
| - HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C, |
| - HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30, |
| - HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10, |
| - HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20, |
| - HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00, |
| - |
| - HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F, |
| - HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08, |
| - HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09, |
| - HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A, |
| - HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B, |
| - HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30, |
| - HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00, |
| - HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10, |
| - HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20, |
| - HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0, |
| - HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00, |
| - HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40, |
| - HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80, |
| - HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0, |
| - |
| - HDMI_FC_AVICONF2_SCALING_MASK = 0x03, |
| - HDMI_FC_AVICONF2_SCALING_NONE = 0x00, |
| - HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01, |
| - HDMI_FC_AVICONF2_SCALING_VERT = 0x02, |
| - HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03, |
| - HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C, |
| - HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00, |
| - HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04, |
| - HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08, |
| - HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70, |
| - HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00, |
| - HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10, |
| - HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20, |
| - HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30, |
| - HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40, |
| - HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80, |
| - HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00, |
| - HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80, |
| - |
| - HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03, |
| - HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00, |
| - HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01, |
| - HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02, |
| - HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03, |
| - HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C, |
| - HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00, |
| - HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04, |
| - |
| -/* FC_DBGFORCE field values */ |
| - HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, |
| - HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, |
| - |
| -/* PHY_CONF0 field values */ |
| - HDMI_PHY_CONF0_PDZ_MASK = 0x80, |
| - HDMI_PHY_CONF0_PDZ_OFFSET = 7, |
| - HDMI_PHY_CONF0_ENTMDS_MASK = 0x40, |
| - HDMI_PHY_CONF0_ENTMDS_OFFSET = 6, |
| - HDMI_PHY_CONF0_SVSRET_MASK = 0x20, |
| - HDMI_PHY_CONF0_SVSRET_OFFSET = 5, |
| - HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10, |
| - HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4, |
| - HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8, |
| - HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3, |
| - HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4, |
| - HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2, |
| - HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2, |
| - HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1, |
| - HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1, |
| - HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0, |
| - |
| -/* PHY_TST0 field values */ |
| - HDMI_PHY_TST0_TSTCLR_MASK = 0x20, |
| - HDMI_PHY_TST0_TSTCLR_OFFSET = 5, |
| - HDMI_PHY_TST0_TSTEN_MASK = 0x10, |
| - HDMI_PHY_TST0_TSTEN_OFFSET = 4, |
| - HDMI_PHY_TST0_TSTCLK_MASK = 0x1, |
| - HDMI_PHY_TST0_TSTCLK_OFFSET = 0, |
| - |
| -/* PHY_STAT0 field values */ |
| - HDMI_PHY_RX_SENSE3 = 0x80, |
| - HDMI_PHY_RX_SENSE2 = 0x40, |
| - HDMI_PHY_RX_SENSE1 = 0x20, |
| - HDMI_PHY_RX_SENSE0 = 0x10, |
| - HDMI_PHY_HPD = 0x02, |
| - HDMI_PHY_TX_PHY_LOCK = 0x01, |
| - |
| -/* PHY_I2CM_SLAVE_ADDR field values */ |
| - HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69, |
| - HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49, |
| - |
| -/* PHY_I2CM_OPERATION_ADDR field values */ |
| - HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10, |
| - HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1, |
| - |
| -/* HDMI_PHY_I2CM_INT_ADDR */ |
| - HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08, |
| - HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04, |
| - |
| -/* HDMI_PHY_I2CM_CTLINT_ADDR */ |
| - HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80, |
| - HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40, |
| - HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08, |
| - HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04, |
| - |
| -/* AUD_CONF0 field values */ |
| - HDMI_AUD_CONF0_SW_RESET = 0x80, |
| - HDMI_AUD_CONF0_I2S_ALL_ENABLE = 0x2F, |
| - |
| -/* AUD_CONF1 field values */ |
| - HDMI_AUD_CONF1_MODE_I2S = 0x00, |
| - HDMI_AUD_CONF1_MODE_RIGHT_J = 0x02, |
| - HDMI_AUD_CONF1_MODE_LEFT_J = 0x04, |
| - HDMI_AUD_CONF1_WIDTH_16 = 0x10, |
| - HDMI_AUD_CONF1_WIDTH_24 = 0x18, |
| - |
| -/* AUD_CTS3 field values */ |
| - HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5, |
| - HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0, |
| - HDMI_AUD_CTS3_N_SHIFT_1 = 0, |
| - HDMI_AUD_CTS3_N_SHIFT_16 = 0x20, |
| - HDMI_AUD_CTS3_N_SHIFT_32 = 0x40, |
| - HDMI_AUD_CTS3_N_SHIFT_64 = 0x60, |
| - HDMI_AUD_CTS3_N_SHIFT_128 = 0x80, |
| - HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0, |
| - /* note that the CTS3 MANUAL bit has been removed |
| - from our part. Can't set it, will read as 0. */ |
| - HDMI_AUD_CTS3_CTS_MANUAL = 0x10, |
| - HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f, |
| - |
| -/* HDMI_AUD_INPUTCLKFS field values */ |
| - HDMI_AUD_INPUTCLKFS_128FS = 0, |
| - HDMI_AUD_INPUTCLKFS_256FS = 1, |
| - HDMI_AUD_INPUTCLKFS_512FS = 2, |
| - HDMI_AUD_INPUTCLKFS_64FS = 4, |
| - |
| -/* AHB_DMA_CONF0 field values */ |
| - HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7, |
| - HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80, |
| - HDMI_AHB_DMA_CONF0_HBR = 0x10, |
| - HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3, |
| - HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08, |
| - HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1, |
| - HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06, |
| - HDMI_AHB_DMA_CONF0_INCR4 = 0x0, |
| - HDMI_AHB_DMA_CONF0_INCR8 = 0x2, |
| - HDMI_AHB_DMA_CONF0_INCR16 = 0x4, |
| - HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1, |
| - |
| -/* HDMI_AHB_DMA_START field values */ |
| - HDMI_AHB_DMA_START_START_OFFSET = 0, |
| - HDMI_AHB_DMA_START_START_MASK = 0x01, |
| - |
| -/* HDMI_AHB_DMA_STOP field values */ |
| - HDMI_AHB_DMA_STOP_STOP_OFFSET = 0, |
| - HDMI_AHB_DMA_STOP_STOP_MASK = 0x01, |
| - |
| -/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */ |
| - HDMI_AHB_DMA_DONE = 0x80, |
| - HDMI_AHB_DMA_RETRY_SPLIT = 0x40, |
| - HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20, |
| - HDMI_AHB_DMA_ERROR = 0x10, |
| - HDMI_AHB_DMA_FIFO_THREMPTY = 0x04, |
| - HDMI_AHB_DMA_FIFO_FULL = 0x02, |
| - HDMI_AHB_DMA_FIFO_EMPTY = 0x01, |
| - |
| -/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT,AHB_DMA_BUFFMASK,AHB_DMA_BUFFPOL values */ |
| - HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02, |
| - HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01, |
| - |
| -/* MC_CLKDIS field values */ |
| - HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40, |
| - HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20, |
| - HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10, |
| - HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8, |
| - HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4, |
| - HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2, |
| - HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1, |
| - |
| -/* MC_SWRSTZ field values */ |
| - HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02, |
| - |
| -/* MC_FLOWCTRL field values */ |
| - HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1, |
| - HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1, |
| - HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0, |
| - |
| -/* MC_PHYRSTZ field values */ |
| - HDMI_MC_PHYRSTZ_PHYRSTZ = 0x01, |
| - |
| -/* MC_HEACPHY_RST field values */ |
| - HDMI_MC_HEACPHY_RST_ASSERT = 0x1, |
| - HDMI_MC_HEACPHY_RST_DEASSERT = 0x0, |
| - |
| -/* CSC_CFG field values */ |
| - HDMI_CSC_CFG_INTMODE_MASK = 0x30, |
| - HDMI_CSC_CFG_INTMODE_OFFSET = 4, |
| - HDMI_CSC_CFG_INTMODE_DISABLE = 0x00, |
| - HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10, |
| - HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20, |
| - HDMI_CSC_CFG_DECMODE_MASK = 0x3, |
| - HDMI_CSC_CFG_DECMODE_OFFSET = 0, |
| - HDMI_CSC_CFG_DECMODE_DISABLE = 0x0, |
| - HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1, |
| - HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2, |
| - HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3, |
| - |
| -/* CSC_SCALE field values */ |
| - HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0, |
| - HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00, |
| - HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50, |
| - HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60, |
| - HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70, |
| - HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03, |
| - |
| -/* A_HDCPCFG0 field values */ |
| - HDMI_A_HDCPCFG0_ELVENA_MASK = 0x80, |
| - HDMI_A_HDCPCFG0_ELVENA_ENABLE = 0x80, |
| - HDMI_A_HDCPCFG0_ELVENA_DISABLE = 0x00, |
| - HDMI_A_HDCPCFG0_I2CFASTMODE_MASK = 0x40, |
| - HDMI_A_HDCPCFG0_I2CFASTMODE_ENABLE = 0x40, |
| - HDMI_A_HDCPCFG0_I2CFASTMODE_DISABLE = 0x00, |
| - HDMI_A_HDCPCFG0_BYPENCRYPTION_MASK = 0x20, |
| - HDMI_A_HDCPCFG0_BYPENCRYPTION_ENABLE = 0x20, |
| - HDMI_A_HDCPCFG0_BYPENCRYPTION_DISABLE = 0x00, |
| - HDMI_A_HDCPCFG0_SYNCRICHECK_MASK = 0x10, |
| - HDMI_A_HDCPCFG0_SYNCRICHECK_ENABLE = 0x10, |
| - HDMI_A_HDCPCFG0_SYNCRICHECK_DISABLE = 0x00, |
| - HDMI_A_HDCPCFG0_AVMUTE_MASK = 0x8, |
| - HDMI_A_HDCPCFG0_AVMUTE_ENABLE = 0x8, |
| - HDMI_A_HDCPCFG0_AVMUTE_DISABLE = 0x0, |
| - HDMI_A_HDCPCFG0_RXDETECT_MASK = 0x4, |
| - HDMI_A_HDCPCFG0_RXDETECT_ENABLE = 0x4, |
| - HDMI_A_HDCPCFG0_RXDETECT_DISABLE = 0x0, |
| - HDMI_A_HDCPCFG0_EN11FEATURE_MASK = 0x2, |
| - HDMI_A_HDCPCFG0_EN11FEATURE_ENABLE = 0x2, |
| - HDMI_A_HDCPCFG0_EN11FEATURE_DISABLE = 0x0, |
| - HDMI_A_HDCPCFG0_HDMIDVI_MASK = 0x1, |
| - HDMI_A_HDCPCFG0_HDMIDVI_HDMI = 0x1, |
| - HDMI_A_HDCPCFG0_HDMIDVI_DVI = 0x0, |
| - |
| -/* A_HDCPCFG1 field values */ |
| - HDMI_A_HDCPCFG1_DISSHA1CHECK_MASK = 0x8, |
| - HDMI_A_HDCPCFG1_DISSHA1CHECK_DISABLE = 0x8, |
| - HDMI_A_HDCPCFG1_DISSHA1CHECK_ENABLE = 0x0, |
| - HDMI_A_HDCPCFG1_PH2UPSHFTENC_MASK = 0x4, |
| - HDMI_A_HDCPCFG1_PH2UPSHFTENC_ENABLE = 0x4, |
| - HDMI_A_HDCPCFG1_PH2UPSHFTENC_DISABLE = 0x0, |
| - HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK = 0x2, |
| - HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE = 0x2, |
| - HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_ENABLE = 0x0, |
| - HDMI_A_HDCPCFG1_SWRESET_MASK = 0x1, |
| - HDMI_A_HDCPCFG1_SWRESET_ASSERT = 0x0, |
| - |
| -/* A_VIDPOLCFG field values */ |
| - HDMI_A_VIDPOLCFG_UNENCRYPTCONF_MASK = 0x60, |
| - HDMI_A_VIDPOLCFG_UNENCRYPTCONF_OFFSET = 5, |
| - HDMI_A_VIDPOLCFG_DATAENPOL_MASK = 0x10, |
| - HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH = 0x10, |
| - HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW = 0x0, |
| - HDMI_A_VIDPOLCFG_VSYNCPOL_MASK = 0x8, |
| - HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_HIGH = 0x8, |
| - HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_LOW = 0x0, |
| - HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2, |
| - HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2, |
| - HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0, |
| - |
| -/* I2CM_OPERATION field values */ |
| - HDMI_I2CM_OPERATION_WRITE = 0x10, |
| - HDMI_I2CM_OPERATION_READ_EXT = 0x2, |
| - HDMI_I2CM_OPERATION_READ = 0x1, |
| - |
| -/* I2CM_INT field values */ |
| - HDMI_I2CM_INT_DONE_POL = 0x8, |
| - HDMI_I2CM_INT_DONE_MASK = 0x4, |
| - |
| -/* I2CM_CTLINT field values */ |
| - HDMI_I2CM_CTLINT_NAC_POL = 0x80, |
| - HDMI_I2CM_CTLINT_NAC_MASK = 0x40, |
| - HDMI_I2CM_CTLINT_ARB_POL = 0x8, |
| - HDMI_I2CM_CTLINT_ARB_MASK = 0x4, |
| -}; |
| - |
| -/* |
| - * HDMI 3D TX PHY registers |
| - */ |
| -#define HDMI_3D_TX_PHY_PWRCTRL 0x00 |
| -#define HDMI_3D_TX_PHY_SERDIVCTRL 0x01 |
| -#define HDMI_3D_TX_PHY_SERCKCTRL 0x02 |
| -#define HDMI_3D_TX_PHY_SERCKKILLCTRL 0x03 |
| -#define HDMI_3D_TX_PHY_TXRESCTRL 0x04 |
| -#define HDMI_3D_TX_PHY_CKCALCTRL 0x05 |
| -#define HDMI_3D_TX_PHY_CPCE_CTRL 0x06 |
| -#define HDMI_3D_TX_PHY_TXCLKMEASCTRL 0x07 |
| -#define HDMI_3D_TX_PHY_TXMEASCTRL 0x08 |
| -#define HDMI_3D_TX_PHY_CKSYMTXCTRL 0x09 |
| -#define HDMI_3D_TX_PHY_CMPSEQCTRL 0x0a |
| -#define HDMI_3D_TX_PHY_CMPPWRCTRL 0x0b |
| -#define HDMI_3D_TX_PHY_CMPMODECTRL 0x0c |
| -#define HDMI_3D_TX_PHY_MEASCTRL 0x0d |
| -#define HDMI_3D_TX_PHY_VLEVCTRL 0x0e |
| -#define HDMI_3D_TX_PHY_D2ACTRL 0x0f |
| -#define HDMI_3D_TX_PHY_CURRCTRL 0x10 |
| -#define HDMI_3D_TX_PHY_DRVANACTRL 0x11 |
| -#define HDMI_3D_TX_PHY_PLLMEASCTRL 0x12 |
| -#define HDMI_3D_TX_PHY_PLLPHBYCTRL 0x13 |
| -#define HDMI_3D_TX_PHY_GRP_CTRL 0x14 |
| -#define HDMI_3D_TX_PHY_GMPCTRL 0x15 |
| -#define HDMI_3D_TX_PHY_MPLLMEASCTRL 0x16 |
| -#define HDMI_3D_TX_PHY_MSM_CTRL 0x17 |
| -#define HDMI_3D_TX_PHY_SCRPB_STATUS 0x18 |
| -#define HDMI_3D_TX_PHY_TXTERM 0x19 |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL 0x1a |
| -#define HDMI_3D_TX_PHY_PATTERNGEN 0x1b |
| -#define HDMI_3D_TX_PHY_SDCAP_MODE 0x1c |
| -#define HDMI_3D_TX_PHY_SCOPEMODE 0x1d |
| -#define HDMI_3D_TX_PHY_DIGTXMODE 0x1e |
| -#define HDMI_3D_TX_PHY_STR_STATUS 0x1f |
| -#define HDMI_3D_TX_PHY_SCOPECNT0 0x20 |
| -#define HDMI_3D_TX_PHY_SCOPECNT1 0x21 |
| -#define HDMI_3D_TX_PHY_SCOPECNT2 0x22 |
| -#define HDMI_3D_TX_PHY_SCOPECNTCLK 0x23 |
| -#define HDMI_3D_TX_PHY_SCOPESAMPLE 0x24 |
| -#define HDMI_3D_TX_PHY_SCOPECNTMSB01 0x25 |
| -#define HDMI_3D_TX_PHY_SCOPECNTMSB2CK 0x26 |
| - |
| -/* HDMI_3D_TX_PHY_CKCALCTRL values */ |
| -#define HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE BIT(15) |
| - |
| -/* HDMI_3D_TX_PHY_MSM_CTRL values */ |
| -#define HDMI_3D_TX_PHY_MSM_CTRL_MPLL_PH_SEL_CK BIT(13) |
| -#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_CLK_REF_MPLL (0 << 1) |
| -#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_OFF (1 << 1) |
| -#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_PCLK (2 << 1) |
| -#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK (3 << 1) |
| -#define HDMI_3D_TX_PHY_MSM_CTRL_SCOPE_CK_SEL BIT(0) |
| - |
| -/* HDMI_3D_TX_PHY_PTRPT_ENBL values */ |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_OVERRIDE BIT(15) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT2 BIT(8) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT1 BIT(7) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT0 BIT(6) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_CK_REF_ENB BIT(5) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_RCAL_ENB BIT(4) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_CLK_ALIGN_ENB BIT(3) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_READY BIT(2) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_CKO_WORD_ENB BIT(1) |
| -#define HDMI_3D_TX_PHY_PTRPT_ENBL_REFCLK_ENB BIT(0) |
| - |
| -#endif /* __DW_HDMI_H__ */ |
| --- /dev/null |
| +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig |
| @@ -0,0 +1,23 @@ |
| +config DRM_DW_HDMI |
| + tristate |
| + select DRM_KMS_HELPER |
| + |
| +config DRM_DW_HDMI_AHB_AUDIO |
| + tristate "Synopsys Designware AHB Audio interface" |
| + depends on DRM_DW_HDMI && SND |
| + select SND_PCM |
| + select SND_PCM_ELD |
| + select SND_PCM_IEC958 |
| + help |
| + Support the AHB Audio interface which is part of the Synopsys |
| + Designware HDMI block. This is used in conjunction with |
| + the i.MX6 HDMI driver. |
| + |
| +config DRM_DW_HDMI_I2S_AUDIO |
| + tristate "Synopsys Designware I2S Audio interface" |
| + depends on SND_SOC |
| + depends on DRM_DW_HDMI |
| + select SND_SOC_HDMI_CODEC |
| + help |
| + Support the I2S Audio interface which is part of the Synopsys |
| + Designware HDMI block. |
| --- /dev/null |
| +++ b/drivers/gpu/drm/bridge/synopsys/Makefile |
| @@ -0,0 +1,5 @@ |
| +#ccflags-y := -Iinclude/drm |
| + |
| +obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o |
| +obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o |
| +obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o |
| --- /dev/null |
| +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c |
| @@ -0,0 +1,652 @@ |
| +/* |
| + * DesignWare HDMI audio driver |
| + * |
| + * 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. |
| + * |
| + * Written and tested against the Designware HDMI Tx found in iMX6. |
| + */ |
| +#include <linux/io.h> |
| +#include <linux/interrupt.h> |
| +#include <linux/module.h> |
| +#include <linux/platform_device.h> |
| +#include <drm/bridge/dw_hdmi.h> |
| +#include <drm/drm_edid.h> |
| + |
| +#include <sound/asoundef.h> |
| +#include <sound/core.h> |
| +#include <sound/initval.h> |
| +#include <sound/pcm.h> |
| +#include <sound/pcm_drm_eld.h> |
| +#include <sound/pcm_iec958.h> |
| + |
| +#include "dw-hdmi-audio.h" |
| + |
| +#define DRIVER_NAME "dw-hdmi-ahb-audio" |
| + |
| +/* Provide some bits rather than bit offsets */ |
| +enum { |
| + HDMI_AHB_DMA_CONF0_SW_FIFO_RST = BIT(7), |
| + HDMI_AHB_DMA_CONF0_EN_HLOCK = BIT(3), |
| + HDMI_AHB_DMA_START_START = BIT(0), |
| + HDMI_AHB_DMA_STOP_STOP = BIT(0), |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = BIT(5), |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = BIT(4), |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = BIT(3), |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = BIT(2), |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = BIT(1), |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0), |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL = |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR | |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST | |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY | |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE | |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL | |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY, |
| + HDMI_IH_AHBDMAAUD_STAT0_ERROR = BIT(5), |
| + HDMI_IH_AHBDMAAUD_STAT0_LOST = BIT(4), |
| + HDMI_IH_AHBDMAAUD_STAT0_RETRY = BIT(3), |
| + HDMI_IH_AHBDMAAUD_STAT0_DONE = BIT(2), |
| + HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = BIT(1), |
| + HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0), |
| + HDMI_IH_AHBDMAAUD_STAT0_ALL = |
| + HDMI_IH_AHBDMAAUD_STAT0_ERROR | |
| + HDMI_IH_AHBDMAAUD_STAT0_LOST | |
| + HDMI_IH_AHBDMAAUD_STAT0_RETRY | |
| + HDMI_IH_AHBDMAAUD_STAT0_DONE | |
| + HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL | |
| + HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY, |
| + HDMI_AHB_DMA_CONF0_INCR16 = 2 << 1, |
| + HDMI_AHB_DMA_CONF0_INCR8 = 1 << 1, |
| + HDMI_AHB_DMA_CONF0_INCR4 = 0, |
| + HDMI_AHB_DMA_CONF0_BURST_MODE = BIT(0), |
| + HDMI_AHB_DMA_MASK_DONE = BIT(7), |
| + |
| + HDMI_REVISION_ID = 0x0001, |
| + HDMI_IH_AHBDMAAUD_STAT0 = 0x0109, |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189, |
| + HDMI_FC_AUDICONF2 = 0x1027, |
| + HDMI_FC_AUDSCONF = 0x1063, |
| + HDMI_FC_AUDSCONF_LAYOUT1 = 1 << 0, |
| + HDMI_FC_AUDSCONF_LAYOUT0 = 0 << 0, |
| + HDMI_AHB_DMA_CONF0 = 0x3600, |
| + HDMI_AHB_DMA_START = 0x3601, |
| + HDMI_AHB_DMA_STOP = 0x3602, |
| + HDMI_AHB_DMA_THRSLD = 0x3603, |
| + HDMI_AHB_DMA_STRADDR0 = 0x3604, |
| + HDMI_AHB_DMA_STPADDR0 = 0x3608, |
| + HDMI_AHB_DMA_MASK = 0x3614, |
| + HDMI_AHB_DMA_POL = 0x3615, |
| + HDMI_AHB_DMA_CONF1 = 0x3616, |
| + HDMI_AHB_DMA_BUFFPOL = 0x361a, |
| +}; |
| + |
| +struct dw_hdmi_channel_conf { |
| + u8 conf1; |
| + u8 ca; |
| +}; |
| + |
| +/* |
| + * The default mapping of ALSA channels to HDMI channels and speaker |
| + * allocation bits. Note that we can't do channel remapping here - |
| + * channels must be in the same order. |
| + * |
| + * Mappings for alsa-lib pcm/surround*.conf files: |
| + * |
| + * Front Sur4.0 Sur4.1 Sur5.0 Sur5.1 Sur7.1 |
| + * Channels 2 4 6 6 6 8 |
| + * |
| + * Our mapping from ALSA channel to CEA686D speaker name and HDMI channel: |
| + * |
| + * Number of ALSA channels |
| + * ALSA Channel 2 3 4 5 6 7 8 |
| + * 0 FL:0 = = = = = = |
| + * 1 FR:1 = = = = = = |
| + * 2 FC:3 RL:4 LFE:2 = = = |
| + * 3 RR:5 RL:4 FC:3 = = |
| + * 4 RR:5 RL:4 = = |
| + * 5 RR:5 = = |
| + * 6 RC:6 = |
| + * 7 RLC/FRC RLC/FRC |
| + */ |
| +static struct dw_hdmi_channel_conf default_hdmi_channel_config[7] = { |
| + { 0x03, 0x00 }, /* FL,FR */ |
| + { 0x0b, 0x02 }, /* FL,FR,FC */ |
| + { 0x33, 0x08 }, /* FL,FR,RL,RR */ |
| + { 0x37, 0x09 }, /* FL,FR,LFE,RL,RR */ |
| + { 0x3f, 0x0b }, /* FL,FR,LFE,FC,RL,RR */ |
| + { 0x7f, 0x0f }, /* FL,FR,LFE,FC,RL,RR,RC */ |
| + { 0xff, 0x13 }, /* FL,FR,LFE,FC,RL,RR,[FR]RC,[FR]LC */ |
| +}; |
| + |
| +struct snd_dw_hdmi { |
| + struct snd_card *card; |
| + struct snd_pcm *pcm; |
| + spinlock_t lock; |
| + struct dw_hdmi_audio_data data; |
| + struct snd_pcm_substream *substream; |
| + void (*reformat)(struct snd_dw_hdmi *, size_t, size_t); |
| + void *buf_src; |
| + void *buf_dst; |
| + dma_addr_t buf_addr; |
| + unsigned buf_offset; |
| + unsigned buf_period; |
| + unsigned buf_size; |
| + unsigned channels; |
| + u8 revision; |
| + u8 iec_offset; |
| + u8 cs[192][8]; |
| +}; |
| + |
| +static void dw_hdmi_writel(u32 val, void __iomem *ptr) |
| +{ |
| + writeb_relaxed(val, ptr); |
| + writeb_relaxed(val >> 8, ptr + 1); |
| + writeb_relaxed(val >> 16, ptr + 2); |
| + writeb_relaxed(val >> 24, ptr + 3); |
| +} |
| + |
| +/* |
| + * Convert to hardware format: The userspace buffer contains IEC958 samples, |
| + * with the PCUV bits in bits 31..28 and audio samples in bits 27..4. We |
| + * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio |
| + * samples in 23..0. |
| + * |
| + * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd |
| + * |
| + * Ideally, we could do with having the data properly formatted in userspace. |
| + */ |
| +static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw, |
| + size_t offset, size_t bytes) |
| +{ |
| + u32 *src = dw->buf_src + offset; |
| + u32 *dst = dw->buf_dst + offset; |
| + u32 *end = dw->buf_src + offset + bytes; |
| + |
| + do { |
| + u32 b, sample = *src++; |
| + |
| + b = (sample & 8) << (28 - 3); |
| + |
| + sample >>= 4; |
| + |
| + *dst++ = sample | b; |
| + } while (src < end); |
| +} |
| + |
| +static u32 parity(u32 sample) |
| +{ |
| + sample ^= sample >> 16; |
| + sample ^= sample >> 8; |
| + sample ^= sample >> 4; |
| + sample ^= sample >> 2; |
| + sample ^= sample >> 1; |
| + return (sample & 1) << 27; |
| +} |
| + |
| +static void dw_hdmi_reformat_s24(struct snd_dw_hdmi *dw, |
| + size_t offset, size_t bytes) |
| +{ |
| + u32 *src = dw->buf_src + offset; |
| + u32 *dst = dw->buf_dst + offset; |
| + u32 *end = dw->buf_src + offset + bytes; |
| + |
| + do { |
| + unsigned i; |
| + u8 *cs; |
| + |
| + cs = dw->cs[dw->iec_offset++]; |
| + if (dw->iec_offset >= 192) |
| + dw->iec_offset = 0; |
| + |
| + i = dw->channels; |
| + do { |
| + u32 sample = *src++; |
| + |
| + sample &= ~0xff000000; |
| + sample |= *cs++ << 24; |
| + sample |= parity(sample & ~0xf8000000); |
| + |
| + *dst++ = sample; |
| + } while (--i); |
| + } while (src < end); |
| +} |
| + |
| +static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw, |
| + struct snd_pcm_runtime *runtime) |
| +{ |
| + u8 cs[4]; |
| + unsigned ch, i, j; |
| + |
| + snd_pcm_create_iec958_consumer(runtime, cs, sizeof(cs)); |
| + |
| + memset(dw->cs, 0, sizeof(dw->cs)); |
| + |
| + for (ch = 0; ch < 8; ch++) { |
| + cs[2] &= ~IEC958_AES2_CON_CHANNEL; |
| + cs[2] |= (ch + 1) << 4; |
| + |
| + for (i = 0; i < ARRAY_SIZE(cs); i++) { |
| + unsigned c = cs[i]; |
| + |
| + for (j = 0; j < 8; j++, c >>= 1) |
| + dw->cs[i * 8 + j][ch] = (c & 1) << 2; |
| + } |
| + } |
| + dw->cs[0][0] |= BIT(4); |
| +} |
| + |
| +static void dw_hdmi_start_dma(struct snd_dw_hdmi *dw) |
| +{ |
| + void __iomem *base = dw->data.base; |
| + unsigned offset = dw->buf_offset; |
| + unsigned period = dw->buf_period; |
| + u32 start, stop; |
| + |
| + dw->reformat(dw, offset, period); |
| + |
| + /* Clear all irqs before enabling irqs and starting DMA */ |
| + writeb_relaxed(HDMI_IH_AHBDMAAUD_STAT0_ALL, |
| + base + HDMI_IH_AHBDMAAUD_STAT0); |
| + |
| + start = dw->buf_addr + offset; |
| + stop = start + period - 1; |
| + |
| + /* Setup the hardware start/stop addresses */ |
| + dw_hdmi_writel(start, base + HDMI_AHB_DMA_STRADDR0); |
| + dw_hdmi_writel(stop, base + HDMI_AHB_DMA_STPADDR0); |
| + |
| + writeb_relaxed((u8)~HDMI_AHB_DMA_MASK_DONE, base + HDMI_AHB_DMA_MASK); |
| + writeb(HDMI_AHB_DMA_START_START, base + HDMI_AHB_DMA_START); |
| + |
| + offset += period; |
| + if (offset >= dw->buf_size) |
| + offset = 0; |
| + dw->buf_offset = offset; |
| +} |
| + |
| +static void dw_hdmi_stop_dma(struct snd_dw_hdmi *dw) |
| +{ |
| + /* Disable interrupts before disabling DMA */ |
| + writeb_relaxed(~0, dw->data.base + HDMI_AHB_DMA_MASK); |
| + writeb_relaxed(HDMI_AHB_DMA_STOP_STOP, dw->data.base + HDMI_AHB_DMA_STOP); |
| +} |
| + |
| +static irqreturn_t snd_dw_hdmi_irq(int irq, void *data) |
| +{ |
| + struct snd_dw_hdmi *dw = data; |
| + struct snd_pcm_substream *substream; |
| + unsigned stat; |
| + |
| + stat = readb_relaxed(dw->data.base + HDMI_IH_AHBDMAAUD_STAT0); |
| + if (!stat) |
| + return IRQ_NONE; |
| + |
| + writeb_relaxed(stat, dw->data.base + HDMI_IH_AHBDMAAUD_STAT0); |
| + |
| + substream = dw->substream; |
| + if (stat & HDMI_IH_AHBDMAAUD_STAT0_DONE && substream) { |
| + snd_pcm_period_elapsed(substream); |
| + |
| + spin_lock(&dw->lock); |
| + if (dw->substream) |
| + dw_hdmi_start_dma(dw); |
| + spin_unlock(&dw->lock); |
| + } |
| + |
| + return IRQ_HANDLED; |
| +} |
| + |
| +static struct snd_pcm_hardware dw_hdmi_hw = { |
| + .info = SNDRV_PCM_INFO_INTERLEAVED | |
| + SNDRV_PCM_INFO_BLOCK_TRANSFER | |
| + SNDRV_PCM_INFO_MMAP | |
| + SNDRV_PCM_INFO_MMAP_VALID, |
| + .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | |
| + SNDRV_PCM_FMTBIT_S24_LE, |
| + .rates = SNDRV_PCM_RATE_32000 | |
| + SNDRV_PCM_RATE_44100 | |
| + SNDRV_PCM_RATE_48000 | |
| + SNDRV_PCM_RATE_88200 | |
| + SNDRV_PCM_RATE_96000 | |
| + SNDRV_PCM_RATE_176400 | |
| + SNDRV_PCM_RATE_192000, |
| + .channels_min = 2, |
| + .channels_max = 8, |
| + .buffer_bytes_max = 1024 * 1024, |
| + .period_bytes_min = 256, |
| + .period_bytes_max = 8192, /* ERR004323: must limit to 8k */ |
| + .periods_min = 2, |
| + .periods_max = 16, |
| + .fifo_size = 0, |
| +}; |
| + |
| +static int dw_hdmi_open(struct snd_pcm_substream *substream) |
| +{ |
| + struct snd_pcm_runtime *runtime = substream->runtime; |
| + struct snd_dw_hdmi *dw = substream->private_data; |
| + void __iomem *base = dw->data.base; |
| + int ret; |
| + |
| + runtime->hw = dw_hdmi_hw; |
| + |
| + ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld); |
| + if (ret < 0) |
| + return ret; |
| + |
| + ret = snd_pcm_limit_hw_rates(runtime); |
| + if (ret < 0) |
| + return ret; |
| + |
| + ret = snd_pcm_hw_constraint_integer(runtime, |
| + SNDRV_PCM_HW_PARAM_PERIODS); |
| + if (ret < 0) |
| + return ret; |
| + |
| + /* Limit the buffer size to the size of the preallocated buffer */ |
| + ret = snd_pcm_hw_constraint_minmax(runtime, |
| + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, |
| + 0, substream->dma_buffer.bytes); |
| + if (ret < 0) |
| + return ret; |
| + |
| + /* Clear FIFO */ |
| + writeb_relaxed(HDMI_AHB_DMA_CONF0_SW_FIFO_RST, |
| + base + HDMI_AHB_DMA_CONF0); |
| + |
| + /* Configure interrupt polarities */ |
| + writeb_relaxed(~0, base + HDMI_AHB_DMA_POL); |
| + writeb_relaxed(~0, base + HDMI_AHB_DMA_BUFFPOL); |
| + |
| + /* Keep interrupts masked, and clear any pending */ |
| + writeb_relaxed(~0, base + HDMI_AHB_DMA_MASK); |
| + writeb_relaxed(~0, base + HDMI_IH_AHBDMAAUD_STAT0); |
| + |
| + ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED, |
| + "dw-hdmi-audio", dw); |
| + if (ret) |
| + return ret; |
| + |
| + /* Un-mute done interrupt */ |
| + writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL & |
| + ~HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE, |
| + base + HDMI_IH_MUTE_AHBDMAAUD_STAT0); |
| + |
| + return 0; |
| +} |
| + |
| +static int dw_hdmi_close(struct snd_pcm_substream *substream) |
| +{ |
| + struct snd_dw_hdmi *dw = substream->private_data; |
| + |
| + /* Mute all interrupts */ |
| + writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL, |
| + dw->data.base + HDMI_IH_MUTE_AHBDMAAUD_STAT0); |
| + |
| + free_irq(dw->data.irq, dw); |
| + |
| + return 0; |
| +} |
| + |
| +static int dw_hdmi_hw_free(struct snd_pcm_substream *substream) |
| +{ |
| + return snd_pcm_lib_free_vmalloc_buffer(substream); |
| +} |
| + |
| +static int dw_hdmi_hw_params(struct snd_pcm_substream *substream, |
| + struct snd_pcm_hw_params *params) |
| +{ |
| + /* Allocate the PCM runtime buffer, which is exposed to userspace. */ |
| + return snd_pcm_lib_alloc_vmalloc_buffer(substream, |
| + params_buffer_bytes(params)); |
| +} |
| + |
| +static int dw_hdmi_prepare(struct snd_pcm_substream *substream) |
| +{ |
| + struct snd_pcm_runtime *runtime = substream->runtime; |
| + struct snd_dw_hdmi *dw = substream->private_data; |
| + u8 threshold, conf0, conf1, layout, ca; |
| + |
| + /* Setup as per 3.0.5 FSL 4.1.0 BSP */ |
| + switch (dw->revision) { |
| + case 0x0a: |
| + conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE | |
| + HDMI_AHB_DMA_CONF0_INCR4; |
| + if (runtime->channels == 2) |
| + threshold = 126; |
| + else |
| + threshold = 124; |
| + break; |
| + case 0x1a: |
| + conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE | |
| + HDMI_AHB_DMA_CONF0_INCR8; |
| + threshold = 128; |
| + break; |
| + default: |
| + /* NOTREACHED */ |
| + return -EINVAL; |
| + } |
| + |
| + dw_hdmi_set_sample_rate(dw->data.hdmi, runtime->rate); |
| + |
| + /* Minimum number of bytes in the fifo. */ |
| + runtime->hw.fifo_size = threshold * 32; |
| + |
| + conf0 |= HDMI_AHB_DMA_CONF0_EN_HLOCK; |
| + conf1 = default_hdmi_channel_config[runtime->channels - 2].conf1; |
| + ca = default_hdmi_channel_config[runtime->channels - 2].ca; |
| + |
| + /* |
| + * For >2 channel PCM audio, we need to select layout 1 |
| + * and set an appropriate channel map. |
| + */ |
| + if (runtime->channels > 2) |
| + layout = HDMI_FC_AUDSCONF_LAYOUT1; |
| + else |
| + layout = HDMI_FC_AUDSCONF_LAYOUT0; |
| + |
| + writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD); |
| + writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0); |
| + writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1); |
| + writeb_relaxed(layout, dw->data.base + HDMI_FC_AUDSCONF); |
| + writeb_relaxed(ca, dw->data.base + HDMI_FC_AUDICONF2); |
| + |
| + switch (runtime->format) { |
| + case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: |
| + dw->reformat = dw_hdmi_reformat_iec958; |
| + break; |
| + case SNDRV_PCM_FORMAT_S24_LE: |
| + dw_hdmi_create_cs(dw, runtime); |
| + dw->reformat = dw_hdmi_reformat_s24; |
| + break; |
| + } |
| + dw->iec_offset = 0; |
| + dw->channels = runtime->channels; |
| + dw->buf_src = runtime->dma_area; |
| + dw->buf_dst = substream->dma_buffer.area; |
| + dw->buf_addr = substream->dma_buffer.addr; |
| + dw->buf_period = snd_pcm_lib_period_bytes(substream); |
| + dw->buf_size = snd_pcm_lib_buffer_bytes(substream); |
| + |
| + return 0; |
| +} |
| + |
| +static int dw_hdmi_trigger(struct snd_pcm_substream *substream, int cmd) |
| +{ |
| + struct snd_dw_hdmi *dw = substream->private_data; |
| + unsigned long flags; |
| + int ret = 0; |
| + |
| + switch (cmd) { |
| + case SNDRV_PCM_TRIGGER_START: |
| + spin_lock_irqsave(&dw->lock, flags); |
| + dw->buf_offset = 0; |
| + dw->substream = substream; |
| + dw_hdmi_start_dma(dw); |
| + dw_hdmi_audio_enable(dw->data.hdmi); |
| + spin_unlock_irqrestore(&dw->lock, flags); |
| + substream->runtime->delay = substream->runtime->period_size; |
| + break; |
| + |
| + case SNDRV_PCM_TRIGGER_STOP: |
| + spin_lock_irqsave(&dw->lock, flags); |
| + dw->substream = NULL; |
| + dw_hdmi_stop_dma(dw); |
| + dw_hdmi_audio_disable(dw->data.hdmi); |
| + spin_unlock_irqrestore(&dw->lock, flags); |
| + break; |
| + |
| + default: |
| + ret = -EINVAL; |
| + break; |
| + } |
| + |
| + return ret; |
| +} |
| + |
| +static snd_pcm_uframes_t dw_hdmi_pointer(struct snd_pcm_substream *substream) |
| +{ |
| + struct snd_pcm_runtime *runtime = substream->runtime; |
| + struct snd_dw_hdmi *dw = substream->private_data; |
| + |
| + /* |
| + * We are unable to report the exact hardware position as |
| + * reading the 32-bit DMA position using 8-bit reads is racy. |
| + */ |
| + return bytes_to_frames(runtime, dw->buf_offset); |
| +} |
| + |
| +static struct snd_pcm_ops snd_dw_hdmi_ops = { |
| + .open = dw_hdmi_open, |
| + .close = dw_hdmi_close, |
| + .ioctl = snd_pcm_lib_ioctl, |
| + .hw_params = dw_hdmi_hw_params, |
| + .hw_free = dw_hdmi_hw_free, |
| + .prepare = dw_hdmi_prepare, |
| + .trigger = dw_hdmi_trigger, |
| + .pointer = dw_hdmi_pointer, |
| + .page = snd_pcm_lib_get_vmalloc_page, |
| +}; |
| + |
| +static int snd_dw_hdmi_probe(struct platform_device *pdev) |
| +{ |
| + const struct dw_hdmi_audio_data *data = pdev->dev.platform_data; |
| + struct device *dev = pdev->dev.parent; |
| + struct snd_dw_hdmi *dw; |
| + struct snd_card *card; |
| + struct snd_pcm *pcm; |
| + unsigned revision; |
| + int ret; |
| + |
| + writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL, |
| + data->base + HDMI_IH_MUTE_AHBDMAAUD_STAT0); |
| + revision = readb_relaxed(data->base + HDMI_REVISION_ID); |
| + if (revision != 0x0a && revision != 0x1a) { |
| + dev_err(dev, "dw-hdmi-audio: unknown revision 0x%02x\n", |
| + revision); |
| + return -ENXIO; |
| + } |
| + |
| + ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
| + THIS_MODULE, sizeof(struct snd_dw_hdmi), &card); |
| + if (ret < 0) |
| + return ret; |
| + |
| + strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); |
| + strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname)); |
| + snprintf(card->longname, sizeof(card->longname), |
| + "%s rev 0x%02x, irq %d", card->shortname, revision, |
| + data->irq); |
| + |
| + dw = card->private_data; |
| + dw->card = card; |
| + dw->data = *data; |
| + dw->revision = revision; |
| + |
| + spin_lock_init(&dw->lock); |
| + |
| + ret = snd_pcm_new(card, "DW HDMI", 0, 1, 0, &pcm); |
| + if (ret < 0) |
| + goto err; |
| + |
| + dw->pcm = pcm; |
| + pcm->private_data = dw; |
| + strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); |
| + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops); |
| + |
| + /* |
| + * To support 8-channel 96kHz audio reliably, we need 512k |
| + * to satisfy alsa with our restricted period (ERR004323). |
| + */ |
| + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
| + dev, 128 * 1024, 1024 * 1024); |
| + |
| + ret = snd_card_register(card); |
| + if (ret < 0) |
| + goto err; |
| + |
| + platform_set_drvdata(pdev, dw); |
| + |
| + return 0; |
| + |
| +err: |
| + snd_card_free(card); |
| + return ret; |
| +} |
| + |
| +static int snd_dw_hdmi_remove(struct platform_device *pdev) |
| +{ |
| + struct snd_dw_hdmi *dw = platform_get_drvdata(pdev); |
| + |
| + snd_card_free(dw->card); |
| + |
| + return 0; |
| +} |
| + |
| +#if defined(CONFIG_PM_SLEEP) && defined(IS_NOT_BROKEN) |
| +/* |
| + * This code is fine, but requires implementation in the dw_hdmi_trigger() |
| + * method which is currently missing as I have no way to test this. |
| + */ |
| +static int snd_dw_hdmi_suspend(struct device *dev) |
| +{ |
| + struct snd_dw_hdmi *dw = dev_get_drvdata(dev); |
| + |
| + snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold); |
| + snd_pcm_suspend_all(dw->pcm); |
| + |
| + return 0; |
| +} |
| + |
| +static int snd_dw_hdmi_resume(struct device *dev) |
| +{ |
| + struct snd_dw_hdmi *dw = dev_get_drvdata(dev); |
| + |
| + snd_power_change_state(dw->card, SNDRV_CTL_POWER_D0); |
| + |
| + return 0; |
| +} |
| + |
| +static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend, |
| + snd_dw_hdmi_resume); |
| +#define PM_OPS &snd_dw_hdmi_pm |
| +#else |
| +#define PM_OPS NULL |
| +#endif |
| + |
| +static struct platform_driver snd_dw_hdmi_driver = { |
| + .probe = snd_dw_hdmi_probe, |
| + .remove = snd_dw_hdmi_remove, |
| + .driver = { |
| + .name = DRIVER_NAME, |
| + .pm = PM_OPS, |
| + }, |
| +}; |
| + |
| +module_platform_driver(snd_dw_hdmi_driver); |
| + |
| +MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>"); |
| +MODULE_DESCRIPTION("Synopsis Designware HDMI AHB ALSA interface"); |
| +MODULE_LICENSE("GPL v2"); |
| +MODULE_ALIAS("platform:" DRIVER_NAME); |
| --- /dev/null |
| +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h |
| @@ -0,0 +1,21 @@ |
| +#ifndef DW_HDMI_AUDIO_H |
| +#define DW_HDMI_AUDIO_H |
| + |
| +struct dw_hdmi; |
| + |
| +struct dw_hdmi_audio_data { |
| + phys_addr_t phys; |
| + void __iomem *base; |
| + int irq; |
| + struct dw_hdmi *hdmi; |
| + u8 *eld; |
| +}; |
| + |
| +struct dw_hdmi_i2s_audio_data { |
| + struct dw_hdmi *hdmi; |
| + |
| + void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); |
| + u8 (*read)(struct dw_hdmi *hdmi, int offset); |
| +}; |
| + |
| +#endif |
| --- /dev/null |
| +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c |
| @@ -0,0 +1,141 @@ |
| +/* |
| + * dw-hdmi-i2s-audio.c |
| + * |
| + * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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. |
| + */ |
| +#include <drm/bridge/dw_hdmi.h> |
| + |
| +#include <sound/hdmi-codec.h> |
| + |
| +#include "dw-hdmi.h" |
| +#include "dw-hdmi-audio.h" |
| + |
| +#define DRIVER_NAME "dw-hdmi-i2s-audio" |
| + |
| +static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio, |
| + u8 val, int offset) |
| +{ |
| + struct dw_hdmi *hdmi = audio->hdmi; |
| + |
| + audio->write(hdmi, val, offset); |
| +} |
| + |
| +static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset) |
| +{ |
| + struct dw_hdmi *hdmi = audio->hdmi; |
| + |
| + return audio->read(hdmi, offset); |
| +} |
| + |
| +static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, |
| + struct hdmi_codec_daifmt *fmt, |
| + struct hdmi_codec_params *hparms) |
| +{ |
| + struct dw_hdmi_i2s_audio_data *audio = data; |
| + struct dw_hdmi *hdmi = audio->hdmi; |
| + u8 conf0 = 0; |
| + u8 conf1 = 0; |
| + u8 inputclkfs = 0; |
| + |
| + /* it cares I2S only */ |
| + if ((fmt->fmt != HDMI_I2S) || |
| + (fmt->bit_clk_master | fmt->frame_clk_master)) { |
| + dev_err(dev, "unsupported format/settings\n"); |
| + return -EINVAL; |
| + } |
| + |
| + inputclkfs = HDMI_AUD_INPUTCLKFS_64FS; |
| + conf0 = HDMI_AUD_CONF0_I2S_ALL_ENABLE; |
| + |
| + switch (hparms->sample_width) { |
| + case 16: |
| + conf1 = HDMI_AUD_CONF1_WIDTH_16; |
| + break; |
| + case 24: |
| + case 32: |
| + conf1 = HDMI_AUD_CONF1_WIDTH_24; |
| + break; |
| + } |
| + |
| + dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate); |
| + |
| + hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS); |
| + hdmi_write(audio, conf0, HDMI_AUD_CONF0); |
| + hdmi_write(audio, conf1, HDMI_AUD_CONF1); |
| + |
| + dw_hdmi_audio_enable(hdmi); |
| + |
| + return 0; |
| +} |
| + |
| +static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) |
| +{ |
| + struct dw_hdmi_i2s_audio_data *audio = data; |
| + struct dw_hdmi *hdmi = audio->hdmi; |
| + |
| + dw_hdmi_audio_disable(hdmi); |
| + |
| + hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); |
| +} |
| + |
| +static struct hdmi_codec_ops dw_hdmi_i2s_ops = { |
| + .hw_params = dw_hdmi_i2s_hw_params, |
| + .audio_shutdown = dw_hdmi_i2s_audio_shutdown, |
| +}; |
| + |
| +static int snd_dw_hdmi_probe(struct platform_device *pdev) |
| +{ |
| + struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data; |
| + struct platform_device_info pdevinfo; |
| + struct hdmi_codec_pdata pdata; |
| + struct platform_device *platform; |
| + |
| + pdata.ops = &dw_hdmi_i2s_ops; |
| + pdata.i2s = 1; |
| + pdata.max_i2s_channels = 6; |
| + pdata.data = audio; |
| + |
| + memset(&pdevinfo, 0, sizeof(pdevinfo)); |
| + pdevinfo.parent = pdev->dev.parent; |
| + pdevinfo.id = PLATFORM_DEVID_AUTO; |
| + pdevinfo.name = HDMI_CODEC_DRV_NAME; |
| + pdevinfo.data = &pdata; |
| + pdevinfo.size_data = sizeof(pdata); |
| + pdevinfo.dma_mask = DMA_BIT_MASK(32); |
| + |
| + platform = platform_device_register_full(&pdevinfo); |
| + if (IS_ERR(platform)) |
| + return PTR_ERR(platform); |
| + |
| + dev_set_drvdata(&pdev->dev, platform); |
| + |
| + return 0; |
| +} |
| + |
| +static int snd_dw_hdmi_remove(struct platform_device *pdev) |
| +{ |
| + struct platform_device *platform = dev_get_drvdata(&pdev->dev); |
| + |
| + platform_device_unregister(platform); |
| + |
| + return 0; |
| +} |
| + |
| +static struct platform_driver snd_dw_hdmi_driver = { |
| + .probe = snd_dw_hdmi_probe, |
| + .remove = snd_dw_hdmi_remove, |
| + .driver = { |
| + .name = DRIVER_NAME, |
| + .owner = THIS_MODULE, |
| + }, |
| +}; |
| +module_platform_driver(snd_dw_hdmi_driver); |
| + |
| +MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); |
| +MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface"); |
| +MODULE_LICENSE("GPL v2"); |
| +MODULE_ALIAS("platform:" DRIVER_NAME); |
| --- /dev/null |
| +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |
| @@ -0,0 +1,2314 @@ |
| +/* |
| + * DesignWare High-Definition Multimedia Interface (HDMI) driver |
| + * |
| + * Copyright (C) 2013-2015 Mentor Graphics Inc. |
| + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. |
| + * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> |
| + * |
| + * This program is free software; you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License as published by |
| + * the Free Software Foundation; either version 2 of the License, or |
| + * (at your option) any later version. |
| + * |
| + */ |
| +#include <linux/module.h> |
| +#include <linux/irq.h> |
| +#include <linux/delay.h> |
| +#include <linux/err.h> |
| +#include <linux/clk.h> |
| +#include <linux/hdmi.h> |
| +#include <linux/mutex.h> |
| +#include <linux/of_device.h> |
| +#include <linux/regmap.h> |
| +#include <linux/spinlock.h> |
| + |
| +#include <drm/drm_of.h> |
| +#include <drm/drmP.h> |
| +#include <drm/drm_atomic_helper.h> |
| +#include <drm/drm_crtc_helper.h> |
| +#include <drm/drm_edid.h> |
| +#include <drm/drm_encoder_slave.h> |
| +#include <drm/bridge/dw_hdmi.h> |
| + |
| +#include "dw-hdmi.h" |
| +#include "dw-hdmi-audio.h" |
| + |
| +#define HDMI_EDID_LEN 512 |
| + |
| +#define RGB 0 |
| +#define YCBCR444 1 |
| +#define YCBCR422_16BITS 2 |
| +#define YCBCR422_8BITS 3 |
| +#define XVYCC444 4 |
| + |
| +enum hdmi_datamap { |
| + RGB444_8B = 0x01, |
| + RGB444_10B = 0x03, |
| + RGB444_12B = 0x05, |
| + RGB444_16B = 0x07, |
| + YCbCr444_8B = 0x09, |
| + YCbCr444_10B = 0x0B, |
| + YCbCr444_12B = 0x0D, |
| + YCbCr444_16B = 0x0F, |
| + YCbCr422_8B = 0x16, |
| + YCbCr422_10B = 0x14, |
| + YCbCr422_12B = 0x12, |
| +}; |
| + |
| +static const u16 csc_coeff_default[3][4] = { |
| + { 0x2000, 0x0000, 0x0000, 0x0000 }, |
| + { 0x0000, 0x2000, 0x0000, 0x0000 }, |
| + { 0x0000, 0x0000, 0x2000, 0x0000 } |
| +}; |
| + |
| +static const u16 csc_coeff_rgb_out_eitu601[3][4] = { |
| + { 0x2000, 0x6926, 0x74fd, 0x010e }, |
| + { 0x2000, 0x2cdd, 0x0000, 0x7e9a }, |
| + { 0x2000, 0x0000, 0x38b4, 0x7e3b } |
| +}; |
| + |
| +static const u16 csc_coeff_rgb_out_eitu709[3][4] = { |
| + { 0x2000, 0x7106, 0x7a02, 0x00a7 }, |
| + { 0x2000, 0x3264, 0x0000, 0x7e6d }, |
| + { 0x2000, 0x0000, 0x3b61, 0x7e25 } |
| +}; |
| + |
| +static const u16 csc_coeff_rgb_in_eitu601[3][4] = { |
| + { 0x2591, 0x1322, 0x074b, 0x0000 }, |
| + { 0x6535, 0x2000, 0x7acc, 0x0200 }, |
| + { 0x6acd, 0x7534, 0x2000, 0x0200 } |
| +}; |
| + |
| +static const u16 csc_coeff_rgb_in_eitu709[3][4] = { |
| + { 0x2dc5, 0x0d9b, 0x049e, 0x0000 }, |
| + { 0x62f0, 0x2000, 0x7d11, 0x0200 }, |
| + { 0x6756, 0x78ab, 0x2000, 0x0200 } |
| +}; |
| + |
| +struct hdmi_vmode { |
| + bool mdataenablepolarity; |
| + |
| + unsigned int mpixelclock; |
| + unsigned int mpixelrepetitioninput; |
| + unsigned int mpixelrepetitionoutput; |
| +}; |
| + |
| +struct hdmi_data_info { |
| + unsigned int enc_in_format; |
| + unsigned int enc_out_format; |
| + unsigned int enc_color_depth; |
| + unsigned int colorimetry; |
| + unsigned int pix_repet_factor; |
| + unsigned int hdcp_enable; |
| + struct hdmi_vmode video_mode; |
| +}; |
| + |
| +struct dw_hdmi_i2c { |
| + struct i2c_adapter adap; |
| + |
| + struct mutex lock; /* used to serialize data transfers */ |
| + struct completion cmp; |
| + u8 stat; |
| + |
| + u8 slave_reg; |
| + bool is_regaddr; |
| +}; |
| + |
| +struct dw_hdmi_phy_data { |
| + enum dw_hdmi_phy_type type; |
| + const char *name; |
| + unsigned int gen; |
| + bool has_svsret; |
| + int (*configure)(struct dw_hdmi *hdmi, |
| + const struct dw_hdmi_plat_data *pdata, |
| + unsigned long mpixelclock); |
| +}; |
| + |
| +struct dw_hdmi { |
| + struct drm_connector connector; |
| + struct drm_bridge bridge; |
| + |
| + unsigned int version; |
| + |
| + struct platform_device *audio; |
| + struct device *dev; |
| + struct clk *isfr_clk; |
| + struct clk *iahb_clk; |
| + struct dw_hdmi_i2c *i2c; |
| + |
| + struct hdmi_data_info hdmi_data; |
| + const struct dw_hdmi_plat_data *plat_data; |
| + |
| + int vic; |
| + |
| + u8 edid[HDMI_EDID_LEN]; |
| + bool cable_plugin; |
| + |
| + struct { |
| + const struct dw_hdmi_phy_ops *ops; |
| + const char *name; |
| + void *data; |
| + bool enabled; |
| + } phy; |
| + |
| + struct drm_display_mode previous_mode; |
| + |
| + struct i2c_adapter *ddc; |
| + void __iomem *regs; |
| + bool sink_is_hdmi; |
| + bool sink_has_audio; |
| + |
| + struct mutex mutex; /* for state below and previous_mode */ |
| + enum drm_connector_force force; /* mutex-protected force state */ |
| + bool disabled; /* DRM has disabled our bridge */ |
| + bool bridge_is_on; /* indicates the bridge is on */ |
| + bool rxsense; /* rxsense state */ |
| + u8 phy_mask; /* desired phy int mask settings */ |
| + |
| + spinlock_t audio_lock; |
| + struct mutex audio_mutex; |
| + unsigned int sample_rate; |
| + unsigned int audio_cts; |
| + unsigned int audio_n; |
| + bool audio_enable; |
| + |
| + unsigned int reg_shift; |
| + struct regmap *regm; |
| +}; |
| + |
| +#define HDMI_IH_PHY_STAT0_RX_SENSE \ |
| + (HDMI_IH_PHY_STAT0_RX_SENSE0 | HDMI_IH_PHY_STAT0_RX_SENSE1 | \ |
| + HDMI_IH_PHY_STAT0_RX_SENSE2 | HDMI_IH_PHY_STAT0_RX_SENSE3) |
| + |
| +#define HDMI_PHY_RX_SENSE \ |
| + (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \ |
| + HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3) |
| + |
| +static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) |
| +{ |
| + regmap_write(hdmi->regm, offset << hdmi->reg_shift, val); |
| +} |
| + |
| +static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset) |
| +{ |
| + unsigned int val = 0; |
| + |
| + regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val); |
| + |
| + return val; |
| +} |
| + |
| +static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg) |
| +{ |
| + regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data); |
| +} |
| + |
| +static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, |
| + u8 shift, u8 mask) |
| +{ |
| + hdmi_modb(hdmi, data << shift, mask, reg); |
| +} |
| + |
| +static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi) |
| +{ |
| + /* Software reset */ |
| + hdmi_writeb(hdmi, 0x00, HDMI_I2CM_SOFTRSTZ); |
| + |
| + /* Set Standard Mode speed (determined to be 100KHz on iMX6) */ |
| + hdmi_writeb(hdmi, 0x00, HDMI_I2CM_DIV); |
| + |
| + /* Set done, not acknowledged and arbitration interrupt polarities */ |
| + hdmi_writeb(hdmi, HDMI_I2CM_INT_DONE_POL, HDMI_I2CM_INT); |
| + hdmi_writeb(hdmi, HDMI_I2CM_CTLINT_NAC_POL | HDMI_I2CM_CTLINT_ARB_POL, |
| + HDMI_I2CM_CTLINT); |
| + |
| + /* Clear DONE and ERROR interrupts */ |
| + hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, |
| + HDMI_IH_I2CM_STAT0); |
| + |
| + /* Mute DONE and ERROR interrupts */ |
| + hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, |
| + HDMI_IH_MUTE_I2CM_STAT0); |
| +} |
| + |
| +static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi, |
| + unsigned char *buf, unsigned int length) |
| +{ |
| + struct dw_hdmi_i2c *i2c = hdmi->i2c; |
| + int stat; |
| + |
| + if (!i2c->is_regaddr) { |
| + dev_dbg(hdmi->dev, "set read register address to 0\n"); |
| + i2c->slave_reg = 0x00; |
| + i2c->is_regaddr = true; |
| + } |
| + |
| + while (length--) { |
| + reinit_completion(&i2c->cmp); |
| + |
| + hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS); |
| + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ, |
| + HDMI_I2CM_OPERATION); |
| + |
| + stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); |
| + if (!stat) |
| + return -EAGAIN; |
| + |
| + /* Check for error condition on the bus */ |
| + if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) |
| + return -EIO; |
| + |
| + *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI); |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi, |
| + unsigned char *buf, unsigned int length) |
| +{ |
| + struct dw_hdmi_i2c *i2c = hdmi->i2c; |
| + int stat; |
| + |
| + if (!i2c->is_regaddr) { |
| + /* Use the first write byte as register address */ |
| + i2c->slave_reg = buf[0]; |
| + length--; |
| + buf++; |
| + i2c->is_regaddr = true; |
| + } |
| + |
| + while (length--) { |
| + reinit_completion(&i2c->cmp); |
| + |
| + hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO); |
| + hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS); |
| + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE, |
| + HDMI_I2CM_OPERATION); |
| + |
| + stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); |
| + if (!stat) |
| + return -EAGAIN; |
| + |
| + /* Check for error condition on the bus */ |
| + if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) |
| + return -EIO; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, |
| + struct i2c_msg *msgs, int num) |
| +{ |
| + struct dw_hdmi *hdmi = i2c_get_adapdata(adap); |
| + struct dw_hdmi_i2c *i2c = hdmi->i2c; |
| + u8 addr = msgs[0].addr; |
| + int i, ret = 0; |
| + |
| + dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr); |
| + |
| + for (i = 0; i < num; i++) { |
| + if (msgs[i].addr != addr) { |
| + dev_warn(hdmi->dev, |
| + "unsupported transfer, changed slave address\n"); |
| + return -EOPNOTSUPP; |
| + } |
| + |
| + if (msgs[i].len == 0) { |
| + dev_dbg(hdmi->dev, |
| + "unsupported transfer %d/%d, no data\n", |
| + i + 1, num); |
| + return -EOPNOTSUPP; |
| + } |
| + } |
| + |
| + mutex_lock(&i2c->lock); |
| + |
| + /* Unmute DONE and ERROR interrupts */ |
| + hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0); |
| + |
| + /* Set slave device address taken from the first I2C message */ |
| + hdmi_writeb(hdmi, addr, HDMI_I2CM_SLAVE); |
| + |
| + /* Set slave device register address on transfer */ |
| + i2c->is_regaddr = false; |
| + |
| + for (i = 0; i < num; i++) { |
| + dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n", |
| + i + 1, num, msgs[i].len, msgs[i].flags); |
| + |
| + if (msgs[i].flags & I2C_M_RD) |
| + ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len); |
| + else |
| + ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len); |
| + |
| + if (ret < 0) |
| + break; |
| + } |
| + |
| + if (!ret) |
| + ret = num; |
| + |
| + /* Mute DONE and ERROR interrupts */ |
| + hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE, |
| + HDMI_IH_MUTE_I2CM_STAT0); |
| + |
| + mutex_unlock(&i2c->lock); |
| + |
| + return ret; |
| +} |
| + |
| +static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter) |
| +{ |
| + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
| +} |
| + |
| +static const struct i2c_algorithm dw_hdmi_algorithm = { |
| + .master_xfer = dw_hdmi_i2c_xfer, |
| + .functionality = dw_hdmi_i2c_func, |
| +}; |
| + |
| +static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi) |
| +{ |
| + struct i2c_adapter *adap; |
| + struct dw_hdmi_i2c *i2c; |
| + int ret; |
| + |
| + i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL); |
| + if (!i2c) |
| + return ERR_PTR(-ENOMEM); |
| + |
| + mutex_init(&i2c->lock); |
| + init_completion(&i2c->cmp); |
| + |
| + adap = &i2c->adap; |
| + adap->class = I2C_CLASS_DDC; |
| + adap->owner = THIS_MODULE; |
| + adap->dev.parent = hdmi->dev; |
| + adap->algo = &dw_hdmi_algorithm; |
| + strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name)); |
| + i2c_set_adapdata(adap, hdmi); |
| + |
| + ret = i2c_add_adapter(adap); |
| + if (ret) { |
| + dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name); |
| + devm_kfree(hdmi->dev, i2c); |
| + return ERR_PTR(ret); |
| + } |
| + |
| + hdmi->i2c = i2c; |
| + |
| + dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); |
| + |
| + return adap; |
| +} |
| + |
| +static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, |
| + unsigned int n) |
| +{ |
| + /* Must be set/cleared first */ |
| + hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); |
| + |
| + /* nshift factor = 0 */ |
| + hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); |
| + |
| + hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | |
| + HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); |
| + hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); |
| + hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); |
| + |
| + hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3); |
| + hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2); |
| + hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1); |
| +} |
| + |
| +static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk) |
| +{ |
| + unsigned int n = (128 * freq) / 1000; |
| + unsigned int mult = 1; |
| + |
| + while (freq > 48000) { |
| + mult *= 2; |
| + freq /= 2; |
| + } |
| + |
| + switch (freq) { |
| + case 32000: |
| + if (pixel_clk == 25175000) |
| + n = 4576; |
| + else if (pixel_clk == 27027000) |
| + n = 4096; |
| + else if (pixel_clk == 74176000 || pixel_clk == 148352000) |
| + n = 11648; |
| + else |
| + n = 4096; |
| + n *= mult; |
| + break; |
| + |
| + case 44100: |
| + if (pixel_clk == 25175000) |
| + n = 7007; |
| + else if (pixel_clk == 74176000) |
| + n = 17836; |
| + else if (pixel_clk == 148352000) |
| + n = 8918; |
| + else |
| + n = 6272; |
| + n *= mult; |
| + break; |
| + |
| + case 48000: |
| + if (pixel_clk == 25175000) |
| + n = 6864; |
| + else if (pixel_clk == 27027000) |
| + n = 6144; |
| + else if (pixel_clk == 74176000) |
| + n = 11648; |
| + else if (pixel_clk == 148352000) |
| + n = 5824; |
| + else |
| + n = 6144; |
| + n *= mult; |
| + break; |
| + |
| + default: |
| + break; |
| + } |
| + |
| + return n; |
| +} |
| + |
| +static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, |
| + unsigned long pixel_clk, unsigned int sample_rate) |
| +{ |
| + unsigned long ftdms = pixel_clk; |
| + unsigned int n, cts; |
| + u64 tmp; |
| + |
| + n = hdmi_compute_n(sample_rate, pixel_clk); |
| + |
| + /* |
| + * Compute the CTS value from the N value. Note that CTS and N |
| + * can be up to 20 bits in total, so we need 64-bit math. Also |
| + * note that our TDMS clock is not fully accurate; it is accurate |
| + * to kHz. This can introduce an unnecessary remainder in the |
| + * calculation below, so we don't try to warn about that. |
| + */ |
| + tmp = (u64)ftdms * n; |
| + do_div(tmp, 128 * sample_rate); |
| + cts = tmp; |
| + |
| + dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n", |
| + __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000, |
| + n, cts); |
| + |
| + spin_lock_irq(&hdmi->audio_lock); |
| + hdmi->audio_n = n; |
| + hdmi->audio_cts = cts; |
| + hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0); |
| + spin_unlock_irq(&hdmi->audio_lock); |
| +} |
| + |
| +static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) |
| +{ |
| + mutex_lock(&hdmi->audio_mutex); |
| + hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate); |
| + mutex_unlock(&hdmi->audio_mutex); |
| +} |
| + |
| +static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) |
| +{ |
| + mutex_lock(&hdmi->audio_mutex); |
| + hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock, |
| + hdmi->sample_rate); |
| + mutex_unlock(&hdmi->audio_mutex); |
| +} |
| + |
| +void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) |
| +{ |
| + mutex_lock(&hdmi->audio_mutex); |
| + hdmi->sample_rate = rate; |
| + hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock, |
| + hdmi->sample_rate); |
| + mutex_unlock(&hdmi->audio_mutex); |
| +} |
| +EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); |
| + |
| +void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) |
| +{ |
| + unsigned long flags; |
| + |
| + spin_lock_irqsave(&hdmi->audio_lock, flags); |
| + hdmi->audio_enable = true; |
| + hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); |
| + spin_unlock_irqrestore(&hdmi->audio_lock, flags); |
| +} |
| +EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable); |
| + |
| +void dw_hdmi_audio_disable(struct dw_hdmi *hdmi) |
| +{ |
| + unsigned long flags; |
| + |
| + spin_lock_irqsave(&hdmi->audio_lock, flags); |
| + hdmi->audio_enable = false; |
| + hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); |
| + spin_unlock_irqrestore(&hdmi->audio_lock, flags); |
| +} |
| +EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable); |
| + |
| +/* |
| + * this submodule is responsible for the video data synchronization. |
| + * for example, for RGB 4:4:4 input, the data map is defined as |
| + * pin{47~40} <==> R[7:0] |
| + * pin{31~24} <==> G[7:0] |
| + * pin{15~8} <==> B[7:0] |
| + */ |
| +static void hdmi_video_sample(struct dw_hdmi *hdmi) |
| +{ |
| + int color_format = 0; |
| + u8 val; |
| + |
| + if (hdmi->hdmi_data.enc_in_format == RGB) { |
| + if (hdmi->hdmi_data.enc_color_depth == 8) |
| + color_format = 0x01; |
| + else if (hdmi->hdmi_data.enc_color_depth == 10) |
| + color_format = 0x03; |
| + else if (hdmi->hdmi_data.enc_color_depth == 12) |
| + color_format = 0x05; |
| + else if (hdmi->hdmi_data.enc_color_depth == 16) |
| + color_format = 0x07; |
| + else |
| + return; |
| + } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) { |
| + if (hdmi->hdmi_data.enc_color_depth == 8) |
| + color_format = 0x09; |
| + else if (hdmi->hdmi_data.enc_color_depth == 10) |
| + color_format = 0x0B; |
| + else if (hdmi->hdmi_data.enc_color_depth == 12) |
| + color_format = 0x0D; |
| + else if (hdmi->hdmi_data.enc_color_depth == 16) |
| + color_format = 0x0F; |
| + else |
| + return; |
| + } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) { |
| + if (hdmi->hdmi_data.enc_color_depth == 8) |
| + color_format = 0x16; |
| + else if (hdmi->hdmi_data.enc_color_depth == 10) |
| + color_format = 0x14; |
| + else if (hdmi->hdmi_data.enc_color_depth == 12) |
| + color_format = 0x12; |
| + else |
| + return; |
| + } |
| + |
| + val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE | |
| + ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) & |
| + HDMI_TX_INVID0_VIDEO_MAPPING_MASK); |
| + hdmi_writeb(hdmi, val, HDMI_TX_INVID0); |
| + |
| + /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */ |
| + val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE | |
| + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE | |
| + HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE; |
| + hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING); |
| + hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0); |
| + hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1); |
| + hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0); |
| + hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1); |
| + hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0); |
| + hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1); |
| +} |
| + |
| +static int is_color_space_conversion(struct dw_hdmi *hdmi) |
| +{ |
| + return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format; |
| +} |
| + |
| +static int is_color_space_decimation(struct dw_hdmi *hdmi) |
| +{ |
| + if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS) |
| + return 0; |
| + if (hdmi->hdmi_data.enc_in_format == RGB || |
| + hdmi->hdmi_data.enc_in_format == YCBCR444) |
| + return 1; |
| + return 0; |
| +} |
| + |
| +static int is_color_space_interpolation(struct dw_hdmi *hdmi) |
| +{ |
| + if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS) |
| + return 0; |
| + if (hdmi->hdmi_data.enc_out_format == RGB || |
| + hdmi->hdmi_data.enc_out_format == YCBCR444) |
| + return 1; |
| + return 0; |
| +} |
| + |
| +static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) |
| +{ |
| + const u16 (*csc_coeff)[3][4] = &csc_coeff_default; |
| + unsigned i; |
| + u32 csc_scale = 1; |
| + |
| + if (is_color_space_conversion(hdmi)) { |
| + if (hdmi->hdmi_data.enc_out_format == RGB) { |
| + if (hdmi->hdmi_data.colorimetry == |
| + HDMI_COLORIMETRY_ITU_601) |
| + csc_coeff = &csc_coeff_rgb_out_eitu601; |
| + else |
| + csc_coeff = &csc_coeff_rgb_out_eitu709; |
| + } else if (hdmi->hdmi_data.enc_in_format == RGB) { |
| + if (hdmi->hdmi_data.colorimetry == |
| + HDMI_COLORIMETRY_ITU_601) |
| + csc_coeff = &csc_coeff_rgb_in_eitu601; |
| + else |
| + csc_coeff = &csc_coeff_rgb_in_eitu709; |
| + csc_scale = 0; |
| + } |
| + } |
| + |
| + /* The CSC registers are sequential, alternating MSB then LSB */ |
| + for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) { |
| + u16 coeff_a = (*csc_coeff)[0][i]; |
| + u16 coeff_b = (*csc_coeff)[1][i]; |
| + u16 coeff_c = (*csc_coeff)[2][i]; |
| + |
| + hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2); |
| + hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2); |
| + hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2); |
| + hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2); |
| + hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2); |
| + hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2); |
| + } |
| + |
| + hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK, |
| + HDMI_CSC_SCALE); |
| +} |
| + |
| +static void hdmi_video_csc(struct dw_hdmi *hdmi) |
| +{ |
| + int color_depth = 0; |
| + int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE; |
| + int decimation = 0; |
| + |
| + /* YCC422 interpolation to 444 mode */ |
| + if (is_color_space_interpolation(hdmi)) |
| + interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1; |
| + else if (is_color_space_decimation(hdmi)) |
| + decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3; |
| + |
| + if (hdmi->hdmi_data.enc_color_depth == 8) |
| + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP; |
| + else if (hdmi->hdmi_data.enc_color_depth == 10) |
| + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP; |
| + else if (hdmi->hdmi_data.enc_color_depth == 12) |
| + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP; |
| + else if (hdmi->hdmi_data.enc_color_depth == 16) |
| + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP; |
| + else |
| + return; |
| + |
| + /* Configure the CSC registers */ |
| + hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG); |
| + hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, |
| + HDMI_CSC_SCALE); |
| + |
| + dw_hdmi_update_csc_coeffs(hdmi); |
| +} |
| + |
| +/* |
| + * HDMI video packetizer is used to packetize the data. |
| + * for example, if input is YCC422 mode or repeater is used, |
| + * data should be repacked this module can be bypassed. |
| + */ |
| +static void hdmi_video_packetize(struct dw_hdmi *hdmi) |
| +{ |
| + unsigned int color_depth = 0; |
| + unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit; |
| + unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP; |
| + struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; |
| + u8 val, vp_conf; |
| + |
| + if (hdmi_data->enc_out_format == RGB || |
| + hdmi_data->enc_out_format == YCBCR444) { |
| + if (!hdmi_data->enc_color_depth) { |
| + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; |
| + } else if (hdmi_data->enc_color_depth == 8) { |
| + color_depth = 4; |
| + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; |
| + } else if (hdmi_data->enc_color_depth == 10) { |
| + color_depth = 5; |
| + } else if (hdmi_data->enc_color_depth == 12) { |
| + color_depth = 6; |
| + } else if (hdmi_data->enc_color_depth == 16) { |
| + color_depth = 7; |
| + } else { |
| + return; |
| + } |
| + } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) { |
| + if (!hdmi_data->enc_color_depth || |
| + hdmi_data->enc_color_depth == 8) |
| + remap_size = HDMI_VP_REMAP_YCC422_16bit; |
| + else if (hdmi_data->enc_color_depth == 10) |
| + remap_size = HDMI_VP_REMAP_YCC422_20bit; |
| + else if (hdmi_data->enc_color_depth == 12) |
| + remap_size = HDMI_VP_REMAP_YCC422_24bit; |
| + else |
| + return; |
| + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422; |
| + } else { |
| + return; |
| + } |
| + |
| + /* set the packetizer registers */ |
| + val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & |
| + HDMI_VP_PR_CD_COLOR_DEPTH_MASK) | |
| + ((hdmi_data->pix_repet_factor << |
| + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) & |
| + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK); |
| + hdmi_writeb(hdmi, val, HDMI_VP_PR_CD); |
| + |
| + hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE, |
| + HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF); |
| + |
| + /* Data from pixel repeater block */ |
| + if (hdmi_data->pix_repet_factor > 1) { |
| + vp_conf = HDMI_VP_CONF_PR_EN_ENABLE | |
| + HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER; |
| + } else { /* data from packetizer block */ |
| + vp_conf = HDMI_VP_CONF_PR_EN_DISABLE | |
| + HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER; |
| + } |
| + |
| + hdmi_modb(hdmi, vp_conf, |
| + HDMI_VP_CONF_PR_EN_MASK | |
| + HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF); |
| + |
| + hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET, |
| + HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF); |
| + |
| + hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP); |
| + |
| + if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) { |
| + vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE | |
| + HDMI_VP_CONF_PP_EN_ENABLE | |
| + HDMI_VP_CONF_YCC422_EN_DISABLE; |
| + } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) { |
| + vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE | |
| + HDMI_VP_CONF_PP_EN_DISABLE | |
| + HDMI_VP_CONF_YCC422_EN_ENABLE; |
| + } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) { |
| + vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE | |
| + HDMI_VP_CONF_PP_EN_DISABLE | |
| + HDMI_VP_CONF_YCC422_EN_DISABLE; |
| + } else { |
| + return; |
| + } |
| + |
| + hdmi_modb(hdmi, vp_conf, |
| + HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK | |
| + HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF); |
| + |
| + hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE | |
| + HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE, |
| + HDMI_VP_STUFF_PP_STUFFING_MASK | |
| + HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF); |
| + |
| + hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK, |
| + HDMI_VP_CONF); |
| +} |
| + |
| +/* ----------------------------------------------------------------------------- |
| + * Synopsys PHY Handling |
| + */ |
| + |
| +static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, |
| + unsigned char bit) |
| +{ |
| + hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET, |
| + HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0); |
| +} |
| + |
| +static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec) |
| +{ |
| + u32 val; |
| + |
| + while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) { |
| + if (msec-- == 0) |
| + return false; |
| + udelay(1000); |
| + } |
| + hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0); |
| + |
| + return true; |
| +} |
| + |
| +void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, |
| + unsigned char addr) |
| +{ |
| + hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); |
| + hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); |
| + hdmi_writeb(hdmi, (unsigned char)(data >> 8), |
| + HDMI_PHY_I2CM_DATAO_1_ADDR); |
| + hdmi_writeb(hdmi, (unsigned char)(data >> 0), |
| + HDMI_PHY_I2CM_DATAO_0_ADDR); |
| + hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, |
| + HDMI_PHY_I2CM_OPERATION_ADDR); |
| + hdmi_phy_wait_i2c_done(hdmi, 1000); |
| +} |
| +EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write); |
| + |
| +static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable) |
| +{ |
| + hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0, |
| + HDMI_PHY_CONF0_PDZ_OFFSET, |
| + HDMI_PHY_CONF0_PDZ_MASK); |
| +} |
| + |
| +static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable) |
| +{ |
| + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| + HDMI_PHY_CONF0_ENTMDS_OFFSET, |
| + HDMI_PHY_CONF0_ENTMDS_MASK); |
| +} |
| + |
| +static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable) |
| +{ |
| + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| + HDMI_PHY_CONF0_SVSRET_OFFSET, |
| + HDMI_PHY_CONF0_SVSRET_MASK); |
| +} |
| + |
| +static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable) |
| +{ |
| + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| + HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, |
| + HDMI_PHY_CONF0_GEN2_PDDQ_MASK); |
| +} |
| + |
| +static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable) |
| +{ |
| + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| + HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, |
| + HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); |
| +} |
| + |
| +static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable) |
| +{ |
| + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| + HDMI_PHY_CONF0_SELDATAENPOL_OFFSET, |
| + HDMI_PHY_CONF0_SELDATAENPOL_MASK); |
| +} |
| + |
| +static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable) |
| +{ |
| + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
| + HDMI_PHY_CONF0_SELDIPIF_OFFSET, |
| + HDMI_PHY_CONF0_SELDIPIF_MASK); |
| +} |
| + |
| +static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) |
| +{ |
| + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; |
| + unsigned int i; |
| + u16 val; |
| + |
| + if (phy->gen == 1) { |
| + dw_hdmi_phy_enable_tmds(hdmi, 0); |
| + dw_hdmi_phy_enable_powerdown(hdmi, true); |
| + return; |
| + } |
| + |
| + dw_hdmi_phy_gen2_txpwron(hdmi, 0); |
| + |
| + /* |
| + * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went |
| + * to low power mode. |
| + */ |
| + for (i = 0; i < 5; ++i) { |
| + val = hdmi_readb(hdmi, HDMI_PHY_STAT0); |
| + if (!(val & HDMI_PHY_TX_PHY_LOCK)) |
| + break; |
| + |
| + usleep_range(1000, 2000); |
| + } |
| + |
| + if (val & HDMI_PHY_TX_PHY_LOCK) |
| + dev_warn(hdmi->dev, "PHY failed to power down\n"); |
| + else |
| + dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i); |
| + |
| + dw_hdmi_phy_gen2_pddq(hdmi, 1); |
| +} |
| + |
| +static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) |
| +{ |
| + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; |
| + unsigned int i; |
| + u8 val; |
| + |
| + if (phy->gen == 1) { |
| + dw_hdmi_phy_enable_powerdown(hdmi, false); |
| + |
| + /* Toggle TMDS enable. */ |
| + dw_hdmi_phy_enable_tmds(hdmi, 0); |
| + dw_hdmi_phy_enable_tmds(hdmi, 1); |
| + return 0; |
| + } |
| + |
| + dw_hdmi_phy_gen2_txpwron(hdmi, 1); |
| + dw_hdmi_phy_gen2_pddq(hdmi, 0); |
| + |
| + /* Wait for PHY PLL lock */ |
| + for (i = 0; i < 5; ++i) { |
| + val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; |
| + if (val) |
| + break; |
| + |
| + usleep_range(1000, 2000); |
| + } |
| + |
| + if (!val) { |
| + dev_err(hdmi->dev, "PHY PLL failed to lock\n"); |
| + return -ETIMEDOUT; |
| + } |
| + |
| + dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i); |
| + return 0; |
| +} |
| + |
| +/* |
| + * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available |
| + * information the DWC MHL PHY has the same register layout and is thus also |
| + * supported by this function. |
| + */ |
| +static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, |
| + const struct dw_hdmi_plat_data *pdata, |
| + unsigned long mpixelclock) |
| +{ |
| + const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; |
| + const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; |
| + const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; |
| + |
| + /* PLL/MPLL Cfg - always match on final entry */ |
| + for (; mpll_config->mpixelclock != ~0UL; mpll_config++) |
| + if (mpixelclock <= mpll_config->mpixelclock) |
| + break; |
| + |
| + for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) |
| + if (mpixelclock <= curr_ctrl->mpixelclock) |
| + break; |
| + |
| + for (; phy_config->mpixelclock != ~0UL; phy_config++) |
| + if (mpixelclock <= phy_config->mpixelclock) |
| + break; |
| + |
| + if (mpll_config->mpixelclock == ~0UL || |
| + curr_ctrl->mpixelclock == ~0UL || |
| + phy_config->mpixelclock == ~0UL) |
| + return -EINVAL; |
| + |
| + dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, |
| + HDMI_3D_TX_PHY_CPCE_CTRL); |
| + dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, |
| + HDMI_3D_TX_PHY_GMPCTRL); |
| + dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], |
| + HDMI_3D_TX_PHY_CURRCTRL); |
| + |
| + dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); |
| + dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK, |
| + HDMI_3D_TX_PHY_MSM_CTRL); |
| + |
| + dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM); |
| + dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, |
| + HDMI_3D_TX_PHY_CKSYMTXCTRL); |
| + dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, |
| + HDMI_3D_TX_PHY_VLEVCTRL); |
| + |
| + /* Override and disable clock termination. */ |
| + dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE, |
| + HDMI_3D_TX_PHY_CKCALCTRL); |
| + |
| + return 0; |
| +} |
| + |
| +static int hdmi_phy_configure(struct dw_hdmi *hdmi) |
| +{ |
| + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; |
| + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; |
| + unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock; |
| + int ret; |
| + |
| + dw_hdmi_phy_power_off(hdmi); |
| + |
| + /* Leave low power consumption mode by asserting SVSRET. */ |
| + if (phy->has_svsret) |
| + dw_hdmi_phy_enable_svsret(hdmi, 1); |
| + |
| + /* PHY reset. The reset signal is active high on Gen2 PHYs. */ |
| + hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ); |
| + hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ); |
| + |
| + hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST); |
| + |
| + hdmi_phy_test_clear(hdmi, 1); |
| + hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, |
| + HDMI_PHY_I2CM_SLAVE_ADDR); |
| + hdmi_phy_test_clear(hdmi, 0); |
| + |
| + /* Write to the PHY as configured by the platform */ |
| + if (pdata->configure_phy) |
| + ret = pdata->configure_phy(hdmi, pdata, mpixelclock); |
| + else |
| + ret = phy->configure(hdmi, pdata, mpixelclock); |
| + if (ret) { |
| + dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n", |
| + mpixelclock); |
| + return ret; |
| + } |
| + |
| + return dw_hdmi_phy_power_on(hdmi); |
| +} |
| + |
| +static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, |
| + struct drm_display_mode *mode) |
| +{ |
| + int i, ret; |
| + |
| + /* HDMI Phy spec says to do the phy initialization sequence twice */ |
| + for (i = 0; i < 2; i++) { |
| + dw_hdmi_phy_sel_data_en_pol(hdmi, 1); |
| + dw_hdmi_phy_sel_interface_control(hdmi, 0); |
| + |
| + ret = hdmi_phy_configure(hdmi); |
| + if (ret) |
| + return ret; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) |
| +{ |
| + dw_hdmi_phy_power_off(hdmi); |
| +} |
| + |
| +static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, |
| + void *data) |
| +{ |
| + return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? |
| + connector_status_connected : connector_status_disconnected; |
| +} |
| + |
| +static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { |
| + .init = dw_hdmi_phy_init, |
| + .disable = dw_hdmi_phy_disable, |
| + .read_hpd = dw_hdmi_phy_read_hpd, |
| +}; |
| + |
| +/* ----------------------------------------------------------------------------- |
| + * HDMI TX Setup |
| + */ |
| + |
| +static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) |
| +{ |
| + u8 de; |
| + |
| + if (hdmi->hdmi_data.video_mode.mdataenablepolarity) |
| + de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH; |
| + else |
| + de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW; |
| + |
| + /* disable rx detect */ |
| + hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE, |
| + HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0); |
| + |
| + hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG); |
| + |
| + hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE, |
| + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); |
| +} |
| + |
| +static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) |
| +{ |
| + struct hdmi_avi_infoframe frame; |
| + u8 val; |
| + |
| + /* Initialise info frame from DRM mode */ |
| + drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); |
| + |
| + if (hdmi->hdmi_data.enc_out_format == YCBCR444) |
| + frame.colorspace = HDMI_COLORSPACE_YUV444; |
| + else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) |
| + frame.colorspace = HDMI_COLORSPACE_YUV422; |
| + else |
| + frame.colorspace = HDMI_COLORSPACE_RGB; |
| + |
| + /* Set up colorimetry */ |
| + if (hdmi->hdmi_data.enc_out_format == XVYCC444) { |
| + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; |
| + if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) |
| + frame.extended_colorimetry = |
| + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
| + else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/ |
| + frame.extended_colorimetry = |
| + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; |
| + } else if (hdmi->hdmi_data.enc_out_format != RGB) { |
| + frame.colorimetry = hdmi->hdmi_data.colorimetry; |
| + frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
| + } else { /* Carries no data */ |
| + frame.colorimetry = HDMI_COLORIMETRY_NONE; |
| + frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
| + } |
| + |
| + frame.scan_mode = HDMI_SCAN_MODE_NONE; |
| + |
| + /* |
| + * The Designware IP uses a different byte format from standard |
| + * AVI info frames, though generally the bits are in the correct |
| + * bytes. |
| + */ |
| + |
| + /* |
| + * AVI data byte 1 differences: Colorspace in bits 0,1 rather than 5,6, |
| + * scan info in bits 4,5 rather than 0,1 and active aspect present in |
| + * bit 6 rather than 4. |
| + */ |
| + val = (frame.scan_mode & 3) << 4 | (frame.colorspace & 3); |
| + if (frame.active_aspect & 15) |
| + val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT; |
| + if (frame.top_bar || frame.bottom_bar) |
| + val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR; |
| + if (frame.left_bar || frame.right_bar) |
| + val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR; |
| + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0); |
| + |
| + /* AVI data byte 2 differences: none */ |
| + val = ((frame.colorimetry & 0x3) << 6) | |
| + ((frame.picture_aspect & 0x3) << 4) | |
| + (frame.active_aspect & 0xf); |
| + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1); |
| + |
| + /* AVI data byte 3 differences: none */ |
| + val = ((frame.extended_colorimetry & 0x7) << 4) | |
| + ((frame.quantization_range & 0x3) << 2) | |
| + (frame.nups & 0x3); |
| + if (frame.itc) |
| + val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID; |
| + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2); |
| + |
| + /* AVI data byte 4 differences: none */ |
| + val = frame.video_code & 0x7f; |
| + hdmi_writeb(hdmi, val, HDMI_FC_AVIVID); |
| + |
| + /* AVI Data Byte 5- set up input and output pixel repetition */ |
| + val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) << |
| + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) & |
| + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) | |
| + ((hdmi->hdmi_data.video_mode.mpixelrepetitionoutput << |
| + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) & |
| + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK); |
| + hdmi_writeb(hdmi, val, HDMI_FC_PRCONF); |
| + |
| + /* |
| + * AVI data byte 5 differences: content type in 0,1 rather than 4,5, |
| + * ycc range in bits 2,3 rather than 6,7 |
| + */ |
| + val = ((frame.ycc_quantization_range & 0x3) << 2) | |
| + (frame.content_type & 0x3); |
| + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3); |
| + |
| + /* AVI Data Bytes 6-13 */ |
| + hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0); |
| + hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1); |
| + hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0); |
| + hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1); |
| + hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0); |
| + hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1); |
| + hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0); |
| + hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1); |
| +} |
| + |
| +static void hdmi_av_composer(struct dw_hdmi *hdmi, |
| + const struct drm_display_mode *mode) |
| +{ |
| + u8 inv_val; |
| + struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; |
| + int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; |
| + unsigned int vdisplay; |
| + |
| + vmode->mpixelclock = mode->clock * 1000; |
| + |
| + dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); |
| + |
| + /* Set up HDMI_FC_INVIDCONF */ |
| + inv_val = (hdmi->hdmi_data.hdcp_enable ? |
| + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : |
| + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE); |
| + |
| + inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ? |
| + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH : |
| + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW; |
| + |
| + inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ? |
| + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH : |
| + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW; |
| + |
| + inv_val |= (vmode->mdataenablepolarity ? |
| + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH : |
| + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW); |
| + |
| + if (hdmi->vic == 39) |
| + inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH; |
| + else |
| + inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ? |
| + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH : |
| + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW; |
| + |
| + inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ? |
| + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED : |
| + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE; |
| + |
| + inv_val |= hdmi->sink_is_hdmi ? |
| + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE : |
| + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE; |
| + |
| + hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF); |
| + |
| + vdisplay = mode->vdisplay; |
| + vblank = mode->vtotal - mode->vdisplay; |
| + v_de_vs = mode->vsync_start - mode->vdisplay; |
| + vsync_len = mode->vsync_end - mode->vsync_start; |
| + |
| + /* |
| + * When we're setting an interlaced mode, we need |
| + * to adjust the vertical timing to suit. |
| + */ |
| + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
| + vdisplay /= 2; |
| + vblank /= 2; |
| + v_de_vs /= 2; |
| + vsync_len /= 2; |
| + } |
| + |
| + /* Set up horizontal active pixel width */ |
| + hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1); |
| + hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0); |
| + |
| + /* Set up vertical active lines */ |
| + hdmi_writeb(hdmi, vdisplay >> 8, HDMI_FC_INVACTV1); |
| + hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0); |
| + |
| + /* Set up horizontal blanking pixel region width */ |
| + hblank = mode->htotal - mode->hdisplay; |
| + hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1); |
| + hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0); |
| + |
| + /* Set up vertical blanking pixel region width */ |
| + hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK); |
| + |
| + /* Set up HSYNC active edge delay width (in pixel clks) */ |
| + h_de_hs = mode->hsync_start - mode->hdisplay; |
| + hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1); |
| + hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0); |
| + |
| + /* Set up VSYNC active edge delay (in lines) */ |
| + hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY); |
| + |
| + /* Set up HSYNC active pulse width (in pixel clks) */ |
| + hsync_len = mode->hsync_end - mode->hsync_start; |
| + hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1); |
| + hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0); |
| + |
| + /* Set up VSYNC active edge delay (in lines) */ |
| + hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH); |
| +} |
| + |
| +/* HDMI Initialization Step B.4 */ |
| +static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) |
| +{ |
| + u8 clkdis; |
| + |
| + /* control period minimum duration */ |
| + hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR); |
| + hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR); |
| + hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC); |
| + |
| + /* Set to fill TMDS data channels */ |
| + hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM); |
| + hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM); |
| + hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM); |
| + |
| + /* Enable pixel clock and tmds data path */ |
| + clkdis = 0x7F; |
| + clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; |
| + hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); |
| + |
| + clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE; |
| + hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); |
| + |
| + /* Enable csc path */ |
| + if (is_color_space_conversion(hdmi)) { |
| + clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; |
| + hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); |
| + } |
| + |
| + /* Enable color space conversion if needed */ |
| + if (is_color_space_conversion(hdmi)) |
| + hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH, |
| + HDMI_MC_FLOWCTRL); |
| + else |
| + hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS, |
| + HDMI_MC_FLOWCTRL); |
| +} |
| + |
| +static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi) |
| +{ |
| + hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS); |
| +} |
| + |
| +/* Workaround to clear the overflow condition */ |
| +static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) |
| +{ |
| + unsigned int count; |
| + unsigned int i; |
| + u8 val; |
| + |
| + /* |
| + * Under some circumstances the Frame Composer arithmetic unit can miss |
| + * an FC register write due to being busy processing the previous one. |
| + * The issue can be worked around by issuing a TMDS software reset and |
| + * then write one of the FC registers several times. |
| + * |
| + * The number of iterations matters and depends on the HDMI TX revision |
| + * (and possibly on the platform). So far only i.MX6Q (v1.30a) and |
| + * i.MX6DL (v1.31a) have been identified as needing the workaround, with |
| + * 4 and 1 iterations respectively. |
| + */ |
| + |
| + switch (hdmi->version) { |
| + case 0x130a: |
| + count = 4; |
| + break; |
| + case 0x131a: |
| + count = 1; |
| + break; |
| + default: |
| + return; |
| + } |
| + |
| + /* TMDS software reset */ |
| + hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ); |
| + |
| + val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF); |
| + for (i = 0; i < count; i++) |
| + hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF); |
| +} |
| + |
| +static void hdmi_enable_overflow_interrupts(struct dw_hdmi *hdmi) |
| +{ |
| + hdmi_writeb(hdmi, 0, HDMI_FC_MASK2); |
| + hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2); |
| +} |
| + |
| +static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) |
| +{ |
| + hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK, |
| + HDMI_IH_MUTE_FC_STAT2); |
| +} |
| + |
| +static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) |
| +{ |
| + int ret; |
| + |
| + hdmi_disable_overflow_interrupts(hdmi); |
| + |
| + hdmi->vic = drm_match_cea_mode(mode); |
| + |
| + if (!hdmi->vic) { |
| + dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n"); |
| + } else { |
| + dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic); |
| + } |
| + |
| + if ((hdmi->vic == 6) || (hdmi->vic == 7) || |
| + (hdmi->vic == 21) || (hdmi->vic == 22) || |
| + (hdmi->vic == 2) || (hdmi->vic == 3) || |
| + (hdmi->vic == 17) || (hdmi->vic == 18)) |
| + hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; |
| + else |
| + hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; |
| + |
| + hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; |
| + hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; |
| + |
| + /* TODO: Get input format from IPU (via FB driver interface) */ |
| + hdmi->hdmi_data.enc_in_format = RGB; |
| + |
| + hdmi->hdmi_data.enc_out_format = RGB; |
| + |
| + hdmi->hdmi_data.enc_color_depth = 8; |
| + hdmi->hdmi_data.pix_repet_factor = 0; |
| + hdmi->hdmi_data.hdcp_enable = 0; |
| + hdmi->hdmi_data.video_mode.mdataenablepolarity = true; |
| + |
| + /* HDMI Initialization Step B.1 */ |
| + hdmi_av_composer(hdmi, mode); |
| + |
| + /* HDMI Initializateion Step B.2 */ |
| + ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode); |
| + if (ret) |
| + return ret; |
| + hdmi->phy.enabled = true; |
| + |
| + /* HDMI Initialization Step B.3 */ |
| + dw_hdmi_enable_video_path(hdmi); |
| + |
| + if (hdmi->sink_has_audio) { |
| + dev_dbg(hdmi->dev, "sink has audio support\n"); |
| + |
| + /* HDMI Initialization Step E - Configure audio */ |
| + hdmi_clk_regenerator_update_pixel_clock(hdmi); |
| + hdmi_enable_audio_clk(hdmi); |
| + } |
| + |
| + /* not for DVI mode */ |
| + if (hdmi->sink_is_hdmi) { |
| + dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); |
| + |
| + /* HDMI Initialization Step F - Configure AVI InfoFrame */ |
| + hdmi_config_AVI(hdmi, mode); |
| + } else { |
| + dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); |
| + } |
| + |
| + hdmi_video_packetize(hdmi); |
| + hdmi_video_csc(hdmi); |
| + hdmi_video_sample(hdmi); |
| + hdmi_tx_hdcp_config(hdmi); |
| + |
| + dw_hdmi_clear_overflow(hdmi); |
| + if (hdmi->cable_plugin && hdmi->sink_is_hdmi) |
| + hdmi_enable_overflow_interrupts(hdmi); |
| + |
| + return 0; |
| +} |
| + |
| +/* Wait until we are registered to enable interrupts */ |
| +static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi) |
| +{ |
| + hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, |
| + HDMI_PHY_I2CM_INT_ADDR); |
| + |
| + hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL | |
| + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL, |
| + HDMI_PHY_I2CM_CTLINT_ADDR); |
| + |
| + /* enable cable hot plug irq */ |
| + hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); |
| + |
| + /* Clear Hotplug interrupts */ |
| + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, |
| + HDMI_IH_PHY_STAT0); |
| + |
| + return 0; |
| +} |
| + |
| +static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) |
| +{ |
| + u8 ih_mute; |
| + |
| + /* |
| + * Boot up defaults are: |
| + * HDMI_IH_MUTE = 0x03 (disabled) |
| + * HDMI_IH_MUTE_* = 0x00 (enabled) |
| + * |
| + * Disable top level interrupt bits in HDMI block |
| + */ |
| + ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) | |
| + HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT | |
| + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT; |
| + |
| + hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); |
| + |
| + /* by default mask all interrupts */ |
| + hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK); |
| + hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1); |
| + hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2); |
| + hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR); |
| + hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR); |
| + hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT); |
| + hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT); |
| + hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK); |
| + hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK); |
| + hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK); |
| + hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK); |
| + hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT); |
| + hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT); |
| + |
| + /* Disable interrupts in the IH_MUTE_* registers */ |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0); |
| + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0); |
| + |
| + /* Enable top level interrupt bits in HDMI block */ |
| + ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT | |
| + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT); |
| + hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); |
| +} |
| + |
| +static void dw_hdmi_poweron(struct dw_hdmi *hdmi) |
| +{ |
| + hdmi->bridge_is_on = true; |
| + dw_hdmi_setup(hdmi, &hdmi->previous_mode); |
| +} |
| + |
| +static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) |
| +{ |
| + if (hdmi->phy.enabled) { |
| + hdmi->phy.ops->disable(hdmi, hdmi->phy.data); |
| + hdmi->phy.enabled = false; |
| + } |
| + |
| + hdmi->bridge_is_on = false; |
| +} |
| + |
| +static void dw_hdmi_update_power(struct dw_hdmi *hdmi) |
| +{ |
| + int force = hdmi->force; |
| + |
| + if (hdmi->disabled) { |
| + force = DRM_FORCE_OFF; |
| + } else if (force == DRM_FORCE_UNSPECIFIED) { |
| + if (hdmi->rxsense) |
| + force = DRM_FORCE_ON; |
| + else |
| + force = DRM_FORCE_OFF; |
| + } |
| + |
| + if (force == DRM_FORCE_OFF) { |
| + if (hdmi->bridge_is_on) |
| + dw_hdmi_poweroff(hdmi); |
| + } else { |
| + if (!hdmi->bridge_is_on) |
| + dw_hdmi_poweron(hdmi); |
| + } |
| +} |
| + |
| +/* |
| + * Adjust the detection of RXSENSE according to whether we have a forced |
| + * connection mode enabled, or whether we have been disabled. There is |
| + * no point processing RXSENSE interrupts if we have a forced connection |
| + * state, or DRM has us disabled. |
| + * |
| + * We also disable rxsense interrupts when we think we're disconnected |
| + * to avoid floating TDMS signals giving false rxsense interrupts. |
| + * |
| + * Note: we still need to listen for HPD interrupts even when DRM has us |
| + * disabled so that we can detect a connect event. |
| + */ |
| +static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) |
| +{ |
| + u8 old_mask = hdmi->phy_mask; |
| + |
| + if (hdmi->force || hdmi->disabled || !hdmi->rxsense) |
| + hdmi->phy_mask |= HDMI_PHY_RX_SENSE; |
| + else |
| + hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE; |
| + |
| + if (old_mask != hdmi->phy_mask) |
| + hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); |
| +} |
| + |
| +static enum drm_connector_status |
| +dw_hdmi_connector_detect(struct drm_connector *connector, bool force) |
| +{ |
| + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, |
| + connector); |
| + |
| + mutex_lock(&hdmi->mutex); |
| + hdmi->force = DRM_FORCE_UNSPECIFIED; |
| + dw_hdmi_update_power(hdmi); |
| + dw_hdmi_update_phy_mask(hdmi); |
| + mutex_unlock(&hdmi->mutex); |
| + |
| + return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); |
| +} |
| + |
| +static int dw_hdmi_connector_get_modes(struct drm_connector *connector) |
| +{ |
| + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, |
| + connector); |
| + struct edid *edid; |
| + int ret = 0; |
| + |
| + if (!hdmi->ddc) |
| + return 0; |
| + |
| + edid = drm_get_edid(connector, hdmi->ddc); |
| + if (edid) { |
| + dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", |
| + edid->width_cm, edid->height_cm); |
| + |
| + hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); |
| + hdmi->sink_has_audio = drm_detect_monitor_audio(edid); |
| + drm_mode_connector_update_edid_property(connector, edid); |
| + ret = drm_add_edid_modes(connector, edid); |
| + /* Store the ELD */ |
| + drm_edid_to_eld(connector, edid); |
| + kfree(edid); |
| + } else { |
| + dev_dbg(hdmi->dev, "failed to get edid\n"); |
| + } |
| + |
| + return ret; |
| +} |
| + |
| +static enum drm_mode_status |
| +dw_hdmi_connector_mode_valid(struct drm_connector *connector, |
| + struct drm_display_mode *mode) |
| +{ |
| + struct dw_hdmi *hdmi = container_of(connector, |
| + struct dw_hdmi, connector); |
| + enum drm_mode_status mode_status = MODE_OK; |
| + |
| + /* We don't support double-clocked modes */ |
| + if (mode->flags & DRM_MODE_FLAG_DBLCLK) |
| + return MODE_BAD; |
| + |
| + if (hdmi->plat_data->mode_valid) |
| + mode_status = hdmi->plat_data->mode_valid(connector, mode); |
| + |
| + return mode_status; |
| +} |
| + |
| +static void dw_hdmi_connector_force(struct drm_connector *connector) |
| +{ |
| + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, |
| + connector); |
| + |
| + mutex_lock(&hdmi->mutex); |
| + hdmi->force = connector->force; |
| + dw_hdmi_update_power(hdmi); |
| + dw_hdmi_update_phy_mask(hdmi); |
| + mutex_unlock(&hdmi->mutex); |
| +} |
| + |
| +static const struct drm_connector_funcs dw_hdmi_connector_funcs = { |
| + .dpms = drm_atomic_helper_connector_dpms, |
| + .fill_modes = drm_helper_probe_single_connector_modes, |
| + .detect = dw_hdmi_connector_detect, |
| + .destroy = drm_connector_cleanup, |
| + .force = dw_hdmi_connector_force, |
| + .reset = drm_atomic_helper_connector_reset, |
| + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
| + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
| +}; |
| + |
| +static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { |
| + .get_modes = dw_hdmi_connector_get_modes, |
| + .mode_valid = dw_hdmi_connector_mode_valid, |
| + .best_encoder = drm_atomic_helper_best_encoder, |
| +}; |
| + |
| +static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) |
| +{ |
| + struct dw_hdmi *hdmi = bridge->driver_private; |
| + struct drm_encoder *encoder = bridge->encoder; |
| + struct drm_connector *connector = &hdmi->connector; |
| + |
| + connector->interlace_allowed = 1; |
| + connector->polled = DRM_CONNECTOR_POLL_HPD; |
| + |
| + drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); |
| + |
| + drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs, |
| + DRM_MODE_CONNECTOR_HDMIA); |
| + |
| + drm_mode_connector_attach_encoder(connector, encoder); |
| + |
| + return 0; |
| +} |
| + |
| +static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, |
| + struct drm_display_mode *orig_mode, |
| + struct drm_display_mode *mode) |
| +{ |
| + struct dw_hdmi *hdmi = bridge->driver_private; |
| + |
| + mutex_lock(&hdmi->mutex); |
| + |
| + /* Store the display mode for plugin/DKMS poweron events */ |
| + memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); |
| + |
| + mutex_unlock(&hdmi->mutex); |
| +} |
| + |
| +static void dw_hdmi_bridge_disable(struct drm_bridge *bridge) |
| +{ |
| + struct dw_hdmi *hdmi = bridge->driver_private; |
| + |
| + mutex_lock(&hdmi->mutex); |
| + hdmi->disabled = true; |
| + dw_hdmi_update_power(hdmi); |
| + dw_hdmi_update_phy_mask(hdmi); |
| + mutex_unlock(&hdmi->mutex); |
| +} |
| + |
| +static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) |
| +{ |
| + struct dw_hdmi *hdmi = bridge->driver_private; |
| + |
| + mutex_lock(&hdmi->mutex); |
| + hdmi->disabled = false; |
| + dw_hdmi_update_power(hdmi); |
| + dw_hdmi_update_phy_mask(hdmi); |
| + mutex_unlock(&hdmi->mutex); |
| +} |
| + |
| +static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { |
| + .attach = dw_hdmi_bridge_attach, |
| + .enable = dw_hdmi_bridge_enable, |
| + .disable = dw_hdmi_bridge_disable, |
| + .mode_set = dw_hdmi_bridge_mode_set, |
| +}; |
| + |
| +static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi) |
| +{ |
| + struct dw_hdmi_i2c *i2c = hdmi->i2c; |
| + unsigned int stat; |
| + |
| + stat = hdmi_readb(hdmi, HDMI_IH_I2CM_STAT0); |
| + if (!stat) |
| + return IRQ_NONE; |
| + |
| + hdmi_writeb(hdmi, stat, HDMI_IH_I2CM_STAT0); |
| + |
| + i2c->stat = stat; |
| + |
| + complete(&i2c->cmp); |
| + |
| + return IRQ_HANDLED; |
| +} |
| + |
| +static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) |
| +{ |
| + struct dw_hdmi *hdmi = dev_id; |
| + u8 intr_stat; |
| + irqreturn_t ret = IRQ_NONE; |
| + |
| + if (hdmi->i2c) |
| + ret = dw_hdmi_i2c_irq(hdmi); |
| + |
| + intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); |
| + if (intr_stat) { |
| + hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); |
| + return IRQ_WAKE_THREAD; |
| + } |
| + |
| + return ret; |
| +} |
| + |
| +static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) |
| +{ |
| + struct dw_hdmi *hdmi = dev_id; |
| + u8 intr_stat, phy_int_pol, phy_pol_mask, phy_stat; |
| + |
| + intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); |
| + phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); |
| + phy_stat = hdmi_readb(hdmi, HDMI_PHY_STAT0); |
| + |
| + phy_pol_mask = 0; |
| + if (intr_stat & HDMI_IH_PHY_STAT0_HPD) |
| + phy_pol_mask |= HDMI_PHY_HPD; |
| + if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE0) |
| + phy_pol_mask |= HDMI_PHY_RX_SENSE0; |
| + if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE1) |
| + phy_pol_mask |= HDMI_PHY_RX_SENSE1; |
| + if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE2) |
| + phy_pol_mask |= HDMI_PHY_RX_SENSE2; |
| + if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE3) |
| + phy_pol_mask |= HDMI_PHY_RX_SENSE3; |
| + |
| + if (phy_pol_mask) |
| + hdmi_modb(hdmi, ~phy_int_pol, phy_pol_mask, HDMI_PHY_POL0); |
| + |
| + /* |
| + * RX sense tells us whether the TDMS transmitters are detecting |
| + * load - in other words, there's something listening on the |
| + * other end of the link. Use this to decide whether we should |
| + * power on the phy as HPD may be toggled by the sink to merely |
| + * ask the source to re-read the EDID. |
| + */ |
| + if (intr_stat & |
| + (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { |
| + mutex_lock(&hdmi->mutex); |
| + if (!hdmi->disabled && !hdmi->force) { |
| + /* |
| + * If the RX sense status indicates we're disconnected, |
| + * clear the software rxsense status. |
| + */ |
| + if (!(phy_stat & HDMI_PHY_RX_SENSE)) |
| + hdmi->rxsense = false; |
| + |
| + /* |
| + * Only set the software rxsense status when both |
| + * rxsense and hpd indicates we're connected. |
| + * This avoids what seems to be bad behaviour in |
| + * at least iMX6S versions of the phy. |
| + */ |
| + if (phy_stat & HDMI_PHY_HPD) |
| + hdmi->rxsense = true; |
| + |
| + dw_hdmi_update_power(hdmi); |
| + dw_hdmi_update_phy_mask(hdmi); |
| + } |
| + mutex_unlock(&hdmi->mutex); |
| + } |
| + |
| + if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { |
| + dev_dbg(hdmi->dev, "EVENT=%s\n", |
| + phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout"); |
| + if (hdmi->bridge.dev) |
| + drm_helper_hpd_irq_event(hdmi->bridge.dev); |
| + } |
| + |
| + hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0); |
| + hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), |
| + HDMI_IH_MUTE_PHY_STAT0); |
| + |
| + return IRQ_HANDLED; |
| +} |
| + |
| +static const struct dw_hdmi_phy_data dw_hdmi_phys[] = { |
| + { |
| + .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY, |
| + .name = "DWC HDMI TX PHY", |
| + .gen = 1, |
| + }, { |
| + .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC, |
| + .name = "DWC MHL PHY + HEAC PHY", |
| + .gen = 2, |
| + .has_svsret = true, |
| + .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, |
| + }, { |
| + .type = DW_HDMI_PHY_DWC_MHL_PHY, |
| + .name = "DWC MHL PHY", |
| + .gen = 2, |
| + .has_svsret = true, |
| + .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, |
| + }, { |
| + .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC, |
| + .name = "DWC HDMI 3D TX PHY + HEAC PHY", |
| + .gen = 2, |
| + .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, |
| + }, { |
| + .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY, |
| + .name = "DWC HDMI 3D TX PHY", |
| + .gen = 2, |
| + .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, |
| + }, { |
| + .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY, |
| + .name = "DWC HDMI 2.0 TX PHY", |
| + .gen = 2, |
| + .has_svsret = true, |
| + }, { |
| + .type = DW_HDMI_PHY_VENDOR_PHY, |
| + .name = "Vendor PHY", |
| + } |
| +}; |
| + |
| +static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) |
| +{ |
| + unsigned int i; |
| + u8 phy_type; |
| + |
| + phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID); |
| + |
| + if (phy_type == DW_HDMI_PHY_VENDOR_PHY) { |
| + /* Vendor PHYs require support from the glue layer. */ |
| + if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) { |
| + dev_err(hdmi->dev, |
| + "Vendor HDMI PHY not supported by glue layer\n"); |
| + return -ENODEV; |
| + } |
| + |
| + hdmi->phy.ops = hdmi->plat_data->phy_ops; |
| + hdmi->phy.data = hdmi->plat_data->phy_data; |
| + hdmi->phy.name = hdmi->plat_data->phy_name; |
| + return 0; |
| + } |
| + |
| + /* Synopsys PHYs are handled internally. */ |
| + for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) { |
| + if (dw_hdmi_phys[i].type == phy_type) { |
| + hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops; |
| + hdmi->phy.name = dw_hdmi_phys[i].name; |
| + hdmi->phy.data = (void *)&dw_hdmi_phys[i]; |
| + |
| + if (!dw_hdmi_phys[i].configure && |
| + !hdmi->plat_data->configure_phy) { |
| + dev_err(hdmi->dev, "%s requires platform support\n", |
| + hdmi->phy.name); |
| + return -ENODEV; |
| + } |
| + |
| + return 0; |
| + } |
| + } |
| + |
| + dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type); |
| + return -ENODEV; |
| +} |
| + |
| +static const struct regmap_config hdmi_regmap_8bit_config = { |
| + .reg_bits = 32, |
| + .val_bits = 8, |
| + .reg_stride = 1, |
| + .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR, |
| +}; |
| + |
| +static const struct regmap_config hdmi_regmap_32bit_config = { |
| + .reg_bits = 32, |
| + .val_bits = 32, |
| + .reg_stride = 4, |
| + .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2, |
| +}; |
| + |
| +static struct dw_hdmi * |
| +__dw_hdmi_probe(struct platform_device *pdev, |
| + const struct dw_hdmi_plat_data *plat_data) |
| +{ |
| + struct device *dev = &pdev->dev; |
| + struct device_node *np = dev->of_node; |
| + struct platform_device_info pdevinfo; |
| + struct device_node *ddc_node; |
| + struct dw_hdmi *hdmi; |
| + struct resource *iores = NULL; |
| + int irq; |
| + int ret; |
| + u32 val = 1; |
| + u8 prod_id0; |
| + u8 prod_id1; |
| + u8 config0; |
| + u8 config3; |
| + |
| + hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); |
| + if (!hdmi) |
| + return ERR_PTR(-ENOMEM); |
| + |
| + hdmi->plat_data = plat_data; |
| + hdmi->dev = dev; |
| + hdmi->sample_rate = 48000; |
| + hdmi->disabled = true; |
| + hdmi->rxsense = true; |
| + hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE); |
| + |
| + mutex_init(&hdmi->mutex); |
| + mutex_init(&hdmi->audio_mutex); |
| + spin_lock_init(&hdmi->audio_lock); |
| + |
| + ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); |
| + if (ddc_node) { |
| + hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); |
| + of_node_put(ddc_node); |
| + if (!hdmi->ddc) { |
| + dev_dbg(hdmi->dev, "failed to read ddc node\n"); |
| + return ERR_PTR(-EPROBE_DEFER); |
| + } |
| + |
| + } else { |
| + dev_dbg(hdmi->dev, "no ddc property found\n"); |
| + } |
| + |
| + if (!plat_data->regm) { |
| + const struct regmap_config *reg_config; |
| + |
| + of_property_read_u32(np, "reg-io-width", &val); |
| + switch (val) { |
| + case 4: |
| + reg_config = &hdmi_regmap_32bit_config; |
| + hdmi->reg_shift = 2; |
| + break; |
| + case 1: |
| + reg_config = &hdmi_regmap_8bit_config; |
| + break; |
| + default: |
| + dev_err(dev, "reg-io-width must be 1 or 4\n"); |
| + return ERR_PTR(-EINVAL); |
| + } |
| + |
| + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| + hdmi->regs = devm_ioremap_resource(dev, iores); |
| + if (IS_ERR(hdmi->regs)) { |
| + ret = PTR_ERR(hdmi->regs); |
| + goto err_res; |
| + } |
| + |
| + hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config); |
| + if (IS_ERR(hdmi->regm)) { |
| + dev_err(dev, "Failed to configure regmap\n"); |
| + ret = PTR_ERR(hdmi->regm); |
| + goto err_res; |
| + } |
| + } else { |
| + hdmi->regm = plat_data->regm; |
| + } |
| + |
| + hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); |
| + if (IS_ERR(hdmi->isfr_clk)) { |
| + ret = PTR_ERR(hdmi->isfr_clk); |
| + dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret); |
| + goto err_res; |
| + } |
| + |
| + ret = clk_prepare_enable(hdmi->isfr_clk); |
| + if (ret) { |
| + dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret); |
| + goto err_res; |
| + } |
| + |
| + hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); |
| + if (IS_ERR(hdmi->iahb_clk)) { |
| + ret = PTR_ERR(hdmi->iahb_clk); |
| + dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret); |
| + goto err_isfr; |
| + } |
| + |
| + ret = clk_prepare_enable(hdmi->iahb_clk); |
| + if (ret) { |
| + dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret); |
| + goto err_isfr; |
| + } |
| + |
| + /* Product and revision IDs */ |
| + hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8) |
| + | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0); |
| + prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0); |
| + prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1); |
| + |
| + if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX || |
| + (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) { |
| + dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n", |
| + hdmi->version, prod_id0, prod_id1); |
| + ret = -ENODEV; |
| + goto err_iahb; |
| + } |
| + |
| + ret = dw_hdmi_detect_phy(hdmi); |
| + if (ret < 0) |
| + goto err_iahb; |
| + |
| + dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n", |
| + hdmi->version >> 12, hdmi->version & 0xfff, |
| + prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without", |
| + hdmi->phy.name); |
| + |
| + initialize_hdmi_ih_mutes(hdmi); |
| + |
| + irq = platform_get_irq(pdev, 0); |
| + if (irq < 0) { |
| + ret = irq; |
| + goto err_iahb; |
| + } |
| + |
| + ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq, |
| + dw_hdmi_irq, IRQF_SHARED, |
| + dev_name(dev), hdmi); |
| + if (ret) |
| + goto err_iahb; |
| + |
| + /* |
| + * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator |
| + * N and cts values before enabling phy |
| + */ |
| + hdmi_init_clk_regenerator(hdmi); |
| + |
| + /* If DDC bus is not specified, try to register HDMI I2C bus */ |
| + if (!hdmi->ddc) { |
| + hdmi->ddc = dw_hdmi_i2c_adapter(hdmi); |
| + if (IS_ERR(hdmi->ddc)) |
| + hdmi->ddc = NULL; |
| + } |
| + |
| + /* |
| + * Configure registers related to HDMI interrupt |
| + * generation before registering IRQ. |
| + */ |
| + hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); |
| + |
| + /* Clear Hotplug interrupts */ |
| + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, |
| + HDMI_IH_PHY_STAT0); |
| + |
| + hdmi->bridge.driver_private = hdmi; |
| + hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; |
| +#ifdef CONFIG_OF |
| + hdmi->bridge.of_node = pdev->dev.of_node; |
| +#endif |
| + |
| + ret = dw_hdmi_fb_registered(hdmi); |
| + if (ret) |
| + goto err_iahb; |
| + |
| + /* Unmute interrupts */ |
| + hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), |
| + HDMI_IH_MUTE_PHY_STAT0); |
| + |
| + memset(&pdevinfo, 0, sizeof(pdevinfo)); |
| + pdevinfo.parent = dev; |
| + pdevinfo.id = PLATFORM_DEVID_AUTO; |
| + |
| + config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID); |
| + config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID); |
| + |
| + if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) { |
| + struct dw_hdmi_audio_data audio; |
| + |
| + audio.phys = iores->start; |
| + audio.base = hdmi->regs; |
| + audio.irq = irq; |
| + audio.hdmi = hdmi; |
| + audio.eld = hdmi->connector.eld; |
| + |
| + pdevinfo.name = "dw-hdmi-ahb-audio"; |
| + pdevinfo.data = &audio; |
| + pdevinfo.size_data = sizeof(audio); |
| + pdevinfo.dma_mask = DMA_BIT_MASK(32); |
| + hdmi->audio = platform_device_register_full(&pdevinfo); |
| + } else if (config0 & HDMI_CONFIG0_I2S) { |
| + struct dw_hdmi_i2s_audio_data audio; |
| + |
| + audio.hdmi = hdmi; |
| + audio.write = hdmi_writeb; |
| + audio.read = hdmi_readb; |
| + |
| + pdevinfo.name = "dw-hdmi-i2s-audio"; |
| + pdevinfo.data = &audio; |
| + pdevinfo.size_data = sizeof(audio); |
| + pdevinfo.dma_mask = DMA_BIT_MASK(32); |
| + hdmi->audio = platform_device_register_full(&pdevinfo); |
| + } |
| + |
| + /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */ |
| + if (hdmi->i2c) |
| + dw_hdmi_i2c_init(hdmi); |
| + |
| + platform_set_drvdata(pdev, hdmi); |
| + |
| + return hdmi; |
| + |
| +err_iahb: |
| + if (hdmi->i2c) { |
| + i2c_del_adapter(&hdmi->i2c->adap); |
| + hdmi->ddc = NULL; |
| + } |
| + |
| + clk_disable_unprepare(hdmi->iahb_clk); |
| +err_isfr: |
| + clk_disable_unprepare(hdmi->isfr_clk); |
| +err_res: |
| + i2c_put_adapter(hdmi->ddc); |
| + |
| + return ERR_PTR(ret); |
| +} |
| + |
| +static void __dw_hdmi_remove(struct dw_hdmi *hdmi) |
| +{ |
| + if (hdmi->audio && !IS_ERR(hdmi->audio)) |
| + platform_device_unregister(hdmi->audio); |
| + |
| + /* Disable all interrupts */ |
| + hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); |
| + |
| + clk_disable_unprepare(hdmi->iahb_clk); |
| + clk_disable_unprepare(hdmi->isfr_clk); |
| + |
| + if (hdmi->i2c) |
| + i2c_del_adapter(&hdmi->i2c->adap); |
| + else |
| + i2c_put_adapter(hdmi->ddc); |
| +} |
| + |
| +/* ----------------------------------------------------------------------------- |
| + * Probe/remove API, used from platforms based on the DRM bridge API. |
| + */ |
| +int dw_hdmi_probe(struct platform_device *pdev, |
| + const struct dw_hdmi_plat_data *plat_data) |
| +{ |
| + struct dw_hdmi *hdmi; |
| + int ret; |
| + |
| + hdmi = __dw_hdmi_probe(pdev, plat_data); |
| + if (IS_ERR(hdmi)) |
| + return PTR_ERR(hdmi); |
| + |
| + ret = drm_bridge_add(&hdmi->bridge); |
| + if (ret < 0) { |
| + __dw_hdmi_remove(hdmi); |
| + return ret; |
| + } |
| + |
| + return 0; |
| +} |
| +EXPORT_SYMBOL_GPL(dw_hdmi_probe); |
| + |
| +void dw_hdmi_remove(struct platform_device *pdev) |
| +{ |
| + struct dw_hdmi *hdmi = platform_get_drvdata(pdev); |
| + |
| + drm_bridge_remove(&hdmi->bridge); |
| + |
| + __dw_hdmi_remove(hdmi); |
| +} |
| +EXPORT_SYMBOL_GPL(dw_hdmi_remove); |
| + |
| +/* ----------------------------------------------------------------------------- |
| + * Bind/unbind API, used from platforms based on the component framework. |
| + */ |
| +int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, |
| + const struct dw_hdmi_plat_data *plat_data) |
| +{ |
| + struct dw_hdmi *hdmi; |
| + int ret; |
| + |
| + hdmi = __dw_hdmi_probe(pdev, plat_data); |
| + if (IS_ERR(hdmi)) |
| + return PTR_ERR(hdmi); |
| + |
| + ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); |
| + if (ret) { |
| + dw_hdmi_remove(pdev); |
| + DRM_ERROR("Failed to initialize bridge with drm\n"); |
| + return ret; |
| + } |
| + |
| + return 0; |
| +} |
| +EXPORT_SYMBOL_GPL(dw_hdmi_bind); |
| + |
| +void dw_hdmi_unbind(struct device *dev) |
| +{ |
| + struct dw_hdmi *hdmi = dev_get_drvdata(dev); |
| + |
| + __dw_hdmi_remove(hdmi); |
| +} |
| +EXPORT_SYMBOL_GPL(dw_hdmi_unbind); |
| + |
| +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); |
| +MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>"); |
| +MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); |
| +MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>"); |
| +MODULE_DESCRIPTION("DW HDMI transmitter driver"); |
| +MODULE_LICENSE("GPL"); |
| +MODULE_ALIAS("platform:dw-hdmi"); |
| --- /dev/null |
| +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h |
| @@ -0,0 +1,1153 @@ |
| +/* |
| + * Copyright (C) 2011 Freescale Semiconductor, Inc. |
| + * |
| + * This program is free software; you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License as published by |
| + * the Free Software Foundation; either version 2 of the License, or |
| + * (at your option) any later version. |
| + */ |
| + |
| +#ifndef __DW_HDMI_H__ |
| +#define __DW_HDMI_H__ |
| + |
| +/* Identification Registers */ |
| +#define HDMI_DESIGN_ID 0x0000 |
| +#define HDMI_REVISION_ID 0x0001 |
| +#define HDMI_PRODUCT_ID0 0x0002 |
| +#define HDMI_PRODUCT_ID1 0x0003 |
| +#define HDMI_CONFIG0_ID 0x0004 |
| +#define HDMI_CONFIG1_ID 0x0005 |
| +#define HDMI_CONFIG2_ID 0x0006 |
| +#define HDMI_CONFIG3_ID 0x0007 |
| + |
| +/* Interrupt Registers */ |
| +#define HDMI_IH_FC_STAT0 0x0100 |
| +#define HDMI_IH_FC_STAT1 0x0101 |
| +#define HDMI_IH_FC_STAT2 0x0102 |
| +#define HDMI_IH_AS_STAT0 0x0103 |
| +#define HDMI_IH_PHY_STAT0 0x0104 |
| +#define HDMI_IH_I2CM_STAT0 0x0105 |
| +#define HDMI_IH_CEC_STAT0 0x0106 |
| +#define HDMI_IH_VP_STAT0 0x0107 |
| +#define HDMI_IH_I2CMPHY_STAT0 0x0108 |
| +#define HDMI_IH_AHBDMAAUD_STAT0 0x0109 |
| + |
| +#define HDMI_IH_MUTE_FC_STAT0 0x0180 |
| +#define HDMI_IH_MUTE_FC_STAT1 0x0181 |
| +#define HDMI_IH_MUTE_FC_STAT2 0x0182 |
| +#define HDMI_IH_MUTE_AS_STAT0 0x0183 |
| +#define HDMI_IH_MUTE_PHY_STAT0 0x0184 |
| +#define HDMI_IH_MUTE_I2CM_STAT0 0x0185 |
| +#define HDMI_IH_MUTE_CEC_STAT0 0x0186 |
| +#define HDMI_IH_MUTE_VP_STAT0 0x0187 |
| +#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188 |
| +#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189 |
| +#define HDMI_IH_MUTE 0x01FF |
| + |
| +/* Video Sample Registers */ |
| +#define HDMI_TX_INVID0 0x0200 |
| +#define HDMI_TX_INSTUFFING 0x0201 |
| +#define HDMI_TX_GYDATA0 0x0202 |
| +#define HDMI_TX_GYDATA1 0x0203 |
| +#define HDMI_TX_RCRDATA0 0x0204 |
| +#define HDMI_TX_RCRDATA1 0x0205 |
| +#define HDMI_TX_BCBDATA0 0x0206 |
| +#define HDMI_TX_BCBDATA1 0x0207 |
| + |
| +/* Video Packetizer Registers */ |
| +#define HDMI_VP_STATUS 0x0800 |
| +#define HDMI_VP_PR_CD 0x0801 |
| +#define HDMI_VP_STUFF 0x0802 |
| +#define HDMI_VP_REMAP 0x0803 |
| +#define HDMI_VP_CONF 0x0804 |
| +#define HDMI_VP_STAT 0x0805 |
| +#define HDMI_VP_INT 0x0806 |
| +#define HDMI_VP_MASK 0x0807 |
| +#define HDMI_VP_POL 0x0808 |
| + |
| +/* Frame Composer Registers */ |
| +#define HDMI_FC_INVIDCONF 0x1000 |
| +#define HDMI_FC_INHACTV0 0x1001 |
| +#define HDMI_FC_INHACTV1 0x1002 |
| +#define HDMI_FC_INHBLANK0 0x1003 |
| +#define HDMI_FC_INHBLANK1 0x1004 |
| +#define HDMI_FC_INVACTV0 0x1005 |
| +#define HDMI_FC_INVACTV1 0x1006 |
| +#define HDMI_FC_INVBLANK 0x1007 |
| +#define HDMI_FC_HSYNCINDELAY0 0x1008 |
| +#define HDMI_FC_HSYNCINDELAY1 0x1009 |
| +#define HDMI_FC_HSYNCINWIDTH0 0x100A |
| +#define HDMI_FC_HSYNCINWIDTH1 0x100B |
| +#define HDMI_FC_VSYNCINDELAY 0x100C |
| +#define HDMI_FC_VSYNCINWIDTH 0x100D |
| +#define HDMI_FC_INFREQ0 0x100E |
| +#define HDMI_FC_INFREQ1 0x100F |
| +#define HDMI_FC_INFREQ2 0x1010 |
| +#define HDMI_FC_CTRLDUR 0x1011 |
| +#define HDMI_FC_EXCTRLDUR 0x1012 |
| +#define HDMI_FC_EXCTRLSPAC 0x1013 |
| +#define HDMI_FC_CH0PREAM 0x1014 |
| +#define HDMI_FC_CH1PREAM 0x1015 |
| +#define HDMI_FC_CH2PREAM 0x1016 |
| +#define HDMI_FC_AVICONF3 0x1017 |
| +#define HDMI_FC_GCP 0x1018 |
| +#define HDMI_FC_AVICONF0 0x1019 |
| +#define HDMI_FC_AVICONF1 0x101A |
| +#define HDMI_FC_AVICONF2 0x101B |
| +#define HDMI_FC_AVIVID 0x101C |
| +#define HDMI_FC_AVIETB0 0x101D |
| +#define HDMI_FC_AVIETB1 0x101E |
| +#define HDMI_FC_AVISBB0 0x101F |
| +#define HDMI_FC_AVISBB1 0x1020 |
| +#define HDMI_FC_AVIELB0 0x1021 |
| +#define HDMI_FC_AVIELB1 0x1022 |
| +#define HDMI_FC_AVISRB0 0x1023 |
| +#define HDMI_FC_AVISRB1 0x1024 |
| +#define HDMI_FC_AUDICONF0 0x1025 |
| +#define HDMI_FC_AUDICONF1 0x1026 |
| +#define HDMI_FC_AUDICONF2 0x1027 |
| +#define HDMI_FC_AUDICONF3 0x1028 |
| +#define HDMI_FC_VSDIEEEID0 0x1029 |
| +#define HDMI_FC_VSDSIZE 0x102A |
| +#define HDMI_FC_VSDIEEEID1 0x1030 |
| +#define HDMI_FC_VSDIEEEID2 0x1031 |
| +#define HDMI_FC_VSDPAYLOAD0 0x1032 |
| +#define HDMI_FC_VSDPAYLOAD1 0x1033 |
| +#define HDMI_FC_VSDPAYLOAD2 0x1034 |
| +#define HDMI_FC_VSDPAYLOAD3 0x1035 |
| +#define HDMI_FC_VSDPAYLOAD4 0x1036 |
| +#define HDMI_FC_VSDPAYLOAD5 0x1037 |
| +#define HDMI_FC_VSDPAYLOAD6 0x1038 |
| +#define HDMI_FC_VSDPAYLOAD7 0x1039 |
| +#define HDMI_FC_VSDPAYLOAD8 0x103A |
| +#define HDMI_FC_VSDPAYLOAD9 0x103B |
| +#define HDMI_FC_VSDPAYLOAD10 0x103C |
| +#define HDMI_FC_VSDPAYLOAD11 0x103D |
| +#define HDMI_FC_VSDPAYLOAD12 0x103E |
| +#define HDMI_FC_VSDPAYLOAD13 0x103F |
| +#define HDMI_FC_VSDPAYLOAD14 0x1040 |
| +#define HDMI_FC_VSDPAYLOAD15 0x1041 |
| +#define HDMI_FC_VSDPAYLOAD16 0x1042 |
| +#define HDMI_FC_VSDPAYLOAD17 0x1043 |
| +#define HDMI_FC_VSDPAYLOAD18 0x1044 |
| +#define HDMI_FC_VSDPAYLOAD19 0x1045 |
| +#define HDMI_FC_VSDPAYLOAD20 0x1046 |
| +#define HDMI_FC_VSDPAYLOAD21 0x1047 |
| +#define HDMI_FC_VSDPAYLOAD22 0x1048 |
| +#define HDMI_FC_VSDPAYLOAD23 0x1049 |
| +#define HDMI_FC_SPDVENDORNAME0 0x104A |
| +#define HDMI_FC_SPDVENDORNAME1 0x104B |
| +#define HDMI_FC_SPDVENDORNAME2 0x104C |
| +#define HDMI_FC_SPDVENDORNAME3 0x104D |
| +#define HDMI_FC_SPDVENDORNAME4 0x104E |
| +#define HDMI_FC_SPDVENDORNAME5 0x104F |
| +#define HDMI_FC_SPDVENDORNAME6 0x1050 |
| +#define HDMI_FC_SPDVENDORNAME7 0x1051 |
| +#define HDMI_FC_SDPPRODUCTNAME0 0x1052 |
| +#define HDMI_FC_SDPPRODUCTNAME1 0x1053 |
| +#define HDMI_FC_SDPPRODUCTNAME2 0x1054 |
| +#define HDMI_FC_SDPPRODUCTNAME3 0x1055 |
| +#define HDMI_FC_SDPPRODUCTNAME4 0x1056 |
| +#define HDMI_FC_SDPPRODUCTNAME5 0x1057 |
| +#define HDMI_FC_SDPPRODUCTNAME6 0x1058 |
| +#define HDMI_FC_SDPPRODUCTNAME7 0x1059 |
| +#define HDMI_FC_SDPPRODUCTNAME8 0x105A |
| +#define HDMI_FC_SDPPRODUCTNAME9 0x105B |
| +#define HDMI_FC_SDPPRODUCTNAME10 0x105C |
| +#define HDMI_FC_SDPPRODUCTNAME11 0x105D |
| +#define HDMI_FC_SDPPRODUCTNAME12 0x105E |
| +#define HDMI_FC_SDPPRODUCTNAME13 0x105F |
| +#define HDMI_FC_SDPPRODUCTNAME14 0x1060 |
| +#define HDMI_FC_SPDPRODUCTNAME15 0x1061 |
| +#define HDMI_FC_SPDDEVICEINF 0x1062 |
| +#define HDMI_FC_AUDSCONF 0x1063 |
| +#define HDMI_FC_AUDSSTAT 0x1064 |
| +#define HDMI_FC_DATACH0FILL 0x1070 |
| +#define HDMI_FC_DATACH1FILL 0x1071 |
| +#define HDMI_FC_DATACH2FILL 0x1072 |
| +#define HDMI_FC_CTRLQHIGH 0x1073 |
| +#define HDMI_FC_CTRLQLOW 0x1074 |
| +#define HDMI_FC_ACP0 0x1075 |
| +#define HDMI_FC_ACP28 0x1076 |
| +#define HDMI_FC_ACP27 0x1077 |
| +#define HDMI_FC_ACP26 0x1078 |
| +#define HDMI_FC_ACP25 0x1079 |
| +#define HDMI_FC_ACP24 0x107A |
| +#define HDMI_FC_ACP23 0x107B |
| +#define HDMI_FC_ACP22 0x107C |
| +#define HDMI_FC_ACP21 0x107D |
| +#define HDMI_FC_ACP20 0x107E |
| +#define HDMI_FC_ACP19 0x107F |
| +#define HDMI_FC_ACP18 0x1080 |
| +#define HDMI_FC_ACP17 0x1081 |
| +#define HDMI_FC_ACP16 0x1082 |
| +#define HDMI_FC_ACP15 0x1083 |
| +#define HDMI_FC_ACP14 0x1084 |
| +#define HDMI_FC_ACP13 0x1085 |
| +#define HDMI_FC_ACP12 0x1086 |
| +#define HDMI_FC_ACP11 0x1087 |
| +#define HDMI_FC_ACP10 0x1088 |
| +#define HDMI_FC_ACP9 0x1089 |
| +#define HDMI_FC_ACP8 0x108A |
| +#define HDMI_FC_ACP7 0x108B |
| +#define HDMI_FC_ACP6 0x108C |
| +#define HDMI_FC_ACP5 0x108D |
| +#define HDMI_FC_ACP4 0x108E |
| +#define HDMI_FC_ACP3 0x108F |
| +#define HDMI_FC_ACP2 0x1090 |
| +#define HDMI_FC_ACP1 0x1091 |
| +#define HDMI_FC_ISCR1_0 0x1092 |
| +#define HDMI_FC_ISCR1_16 0x1093 |
| +#define HDMI_FC_ISCR1_15 0x1094 |
| +#define HDMI_FC_ISCR1_14 0x1095 |
| +#define HDMI_FC_ISCR1_13 0x1096 |
| +#define HDMI_FC_ISCR1_12 0x1097 |
| +#define HDMI_FC_ISCR1_11 0x1098 |
| +#define HDMI_FC_ISCR1_10 0x1099 |
| +#define HDMI_FC_ISCR1_9 0x109A |
| +#define HDMI_FC_ISCR1_8 0x109B |
| +#define HDMI_FC_ISCR1_7 0x109C |
| +#define HDMI_FC_ISCR1_6 0x109D |
| +#define HDMI_FC_ISCR1_5 0x109E |
| +#define HDMI_FC_ISCR1_4 0x109F |
| +#define HDMI_FC_ISCR1_3 0x10A0 |
| +#define HDMI_FC_ISCR1_2 0x10A1 |
| +#define HDMI_FC_ISCR1_1 0x10A2 |
| +#define HDMI_FC_ISCR2_15 0x10A3 |
| +#define HDMI_FC_ISCR2_14 0x10A4 |
| +#define HDMI_FC_ISCR2_13 0x10A5 |
| +#define HDMI_FC_ISCR2_12 0x10A6 |
| +#define HDMI_FC_ISCR2_11 0x10A7 |
| +#define HDMI_FC_ISCR2_10 0x10A8 |
| +#define HDMI_FC_ISCR2_9 0x10A9 |
| +#define HDMI_FC_ISCR2_8 0x10AA |
| +#define HDMI_FC_ISCR2_7 0x10AB |
| +#define HDMI_FC_ISCR2_6 0x10AC |
| +#define HDMI_FC_ISCR2_5 0x10AD |
| +#define HDMI_FC_ISCR2_4 0x10AE |
| +#define HDMI_FC_ISCR2_3 0x10AF |
| +#define HDMI_FC_ISCR2_2 0x10B0 |
| +#define HDMI_FC_ISCR2_1 0x10B1 |
| +#define HDMI_FC_ISCR2_0 0x10B2 |
| +#define HDMI_FC_DATAUTO0 0x10B3 |
| +#define HDMI_FC_DATAUTO1 0x10B4 |
| +#define HDMI_FC_DATAUTO2 0x10B5 |
| +#define HDMI_FC_DATMAN 0x10B6 |
| +#define HDMI_FC_DATAUTO3 0x10B7 |
| +#define HDMI_FC_RDRB0 0x10B8 |
| +#define HDMI_FC_RDRB1 0x10B9 |
| +#define HDMI_FC_RDRB2 0x10BA |
| +#define HDMI_FC_RDRB3 0x10BB |
| +#define HDMI_FC_RDRB4 0x10BC |
| +#define HDMI_FC_RDRB5 0x10BD |
| +#define HDMI_FC_RDRB6 0x10BE |
| +#define HDMI_FC_RDRB7 0x10BF |
| +#define HDMI_FC_STAT0 0x10D0 |
| +#define HDMI_FC_INT0 0x10D1 |
| +#define HDMI_FC_MASK0 0x10D2 |
| +#define HDMI_FC_POL0 0x10D3 |
| +#define HDMI_FC_STAT1 0x10D4 |
| +#define HDMI_FC_INT1 0x10D5 |
| +#define HDMI_FC_MASK1 0x10D6 |
| +#define HDMI_FC_POL1 0x10D7 |
| +#define HDMI_FC_STAT2 0x10D8 |
| +#define HDMI_FC_INT2 0x10D9 |
| +#define HDMI_FC_MASK2 0x10DA |
| +#define HDMI_FC_POL2 0x10DB |
| +#define HDMI_FC_PRCONF 0x10E0 |
| + |
| +#define HDMI_FC_GMD_STAT 0x1100 |
| +#define HDMI_FC_GMD_EN 0x1101 |
| +#define HDMI_FC_GMD_UP 0x1102 |
| +#define HDMI_FC_GMD_CONF 0x1103 |
| +#define HDMI_FC_GMD_HB 0x1104 |
| +#define HDMI_FC_GMD_PB0 0x1105 |
| +#define HDMI_FC_GMD_PB1 0x1106 |
| +#define HDMI_FC_GMD_PB2 0x1107 |
| +#define HDMI_FC_GMD_PB3 0x1108 |
| +#define HDMI_FC_GMD_PB4 0x1109 |
| +#define HDMI_FC_GMD_PB5 0x110A |
| +#define HDMI_FC_GMD_PB6 0x110B |
| +#define HDMI_FC_GMD_PB7 0x110C |
| +#define HDMI_FC_GMD_PB8 0x110D |
| +#define HDMI_FC_GMD_PB9 0x110E |
| +#define HDMI_FC_GMD_PB10 0x110F |
| +#define HDMI_FC_GMD_PB11 0x1110 |
| +#define HDMI_FC_GMD_PB12 0x1111 |
| +#define HDMI_FC_GMD_PB13 0x1112 |
| +#define HDMI_FC_GMD_PB14 0x1113 |
| +#define HDMI_FC_GMD_PB15 0x1114 |
| +#define HDMI_FC_GMD_PB16 0x1115 |
| +#define HDMI_FC_GMD_PB17 0x1116 |
| +#define HDMI_FC_GMD_PB18 0x1117 |
| +#define HDMI_FC_GMD_PB19 0x1118 |
| +#define HDMI_FC_GMD_PB20 0x1119 |
| +#define HDMI_FC_GMD_PB21 0x111A |
| +#define HDMI_FC_GMD_PB22 0x111B |
| +#define HDMI_FC_GMD_PB23 0x111C |
| +#define HDMI_FC_GMD_PB24 0x111D |
| +#define HDMI_FC_GMD_PB25 0x111E |
| +#define HDMI_FC_GMD_PB26 0x111F |
| +#define HDMI_FC_GMD_PB27 0x1120 |
| + |
| +#define HDMI_FC_DBGFORCE 0x1200 |
| +#define HDMI_FC_DBGAUD0CH0 0x1201 |
| +#define HDMI_FC_DBGAUD1CH0 0x1202 |
| +#define HDMI_FC_DBGAUD2CH0 0x1203 |
| +#define HDMI_FC_DBGAUD0CH1 0x1204 |
| +#define HDMI_FC_DBGAUD1CH1 0x1205 |
| +#define HDMI_FC_DBGAUD2CH1 0x1206 |
| +#define HDMI_FC_DBGAUD0CH2 0x1207 |
| +#define HDMI_FC_DBGAUD1CH2 0x1208 |
| +#define HDMI_FC_DBGAUD2CH2 0x1209 |
| +#define HDMI_FC_DBGAUD0CH3 0x120A |
| +#define HDMI_FC_DBGAUD1CH3 0x120B |
| +#define HDMI_FC_DBGAUD2CH3 0x120C |
| +#define HDMI_FC_DBGAUD0CH4 0x120D |
| +#define HDMI_FC_DBGAUD1CH4 0x120E |
| +#define HDMI_FC_DBGAUD2CH4 0x120F |
| +#define HDMI_FC_DBGAUD0CH5 0x1210 |
| +#define HDMI_FC_DBGAUD1CH5 0x1211 |
| +#define HDMI_FC_DBGAUD2CH5 0x1212 |
| +#define HDMI_FC_DBGAUD0CH6 0x1213 |
| +#define HDMI_FC_DBGAUD1CH6 0x1214 |
| +#define HDMI_FC_DBGAUD2CH6 0x1215 |
| +#define HDMI_FC_DBGAUD0CH7 0x1216 |
| +#define HDMI_FC_DBGAUD1CH7 0x1217 |
| +#define HDMI_FC_DBGAUD2CH7 0x1218 |
| +#define HDMI_FC_DBGTMDS0 0x1219 |
| +#define HDMI_FC_DBGTMDS1 0x121A |
| +#define HDMI_FC_DBGTMDS2 0x121B |
| + |
| +/* HDMI Source PHY Registers */ |
| +#define HDMI_PHY_CONF0 0x3000 |
| +#define HDMI_PHY_TST0 0x3001 |
| +#define HDMI_PHY_TST1 0x3002 |
| +#define HDMI_PHY_TST2 0x3003 |
| +#define HDMI_PHY_STAT0 0x3004 |
| +#define HDMI_PHY_INT0 0x3005 |
| +#define HDMI_PHY_MASK0 0x3006 |
| +#define HDMI_PHY_POL0 0x3007 |
| + |
| +/* HDMI Master PHY Registers */ |
| +#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020 |
| +#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021 |
| +#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022 |
| +#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023 |
| +#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024 |
| +#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025 |
| +#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026 |
| +#define HDMI_PHY_I2CM_INT_ADDR 0x3027 |
| +#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028 |
| +#define HDMI_PHY_I2CM_DIV_ADDR 0x3029 |
| +#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a |
| +#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b |
| +#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c |
| +#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d |
| +#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e |
| +#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f |
| +#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030 |
| +#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031 |
| +#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032 |
| + |
| +/* Audio Sampler Registers */ |
| +#define HDMI_AUD_CONF0 0x3100 |
| +#define HDMI_AUD_CONF1 0x3101 |
| +#define HDMI_AUD_INT 0x3102 |
| +#define HDMI_AUD_CONF2 0x3103 |
| +#define HDMI_AUD_N1 0x3200 |
| +#define HDMI_AUD_N2 0x3201 |
| +#define HDMI_AUD_N3 0x3202 |
| +#define HDMI_AUD_CTS1 0x3203 |
| +#define HDMI_AUD_CTS2 0x3204 |
| +#define HDMI_AUD_CTS3 0x3205 |
| +#define HDMI_AUD_INPUTCLKFS 0x3206 |
| +#define HDMI_AUD_SPDIFINT 0x3302 |
| +#define HDMI_AUD_CONF0_HBR 0x3400 |
| +#define HDMI_AUD_HBR_STATUS 0x3401 |
| +#define HDMI_AUD_HBR_INT 0x3402 |
| +#define HDMI_AUD_HBR_POL 0x3403 |
| +#define HDMI_AUD_HBR_MASK 0x3404 |
| + |
| +/* |
| + * Generic Parallel Audio Interface Registers |
| + * Not used as GPAUD interface is not enabled in hw |
| + */ |
| +#define HDMI_GP_CONF0 0x3500 |
| +#define HDMI_GP_CONF1 0x3501 |
| +#define HDMI_GP_CONF2 0x3502 |
| +#define HDMI_GP_STAT 0x3503 |
| +#define HDMI_GP_INT 0x3504 |
| +#define HDMI_GP_MASK 0x3505 |
| +#define HDMI_GP_POL 0x3506 |
| + |
| +/* Audio DMA Registers */ |
| +#define HDMI_AHB_DMA_CONF0 0x3600 |
| +#define HDMI_AHB_DMA_START 0x3601 |
| +#define HDMI_AHB_DMA_STOP 0x3602 |
| +#define HDMI_AHB_DMA_THRSLD 0x3603 |
| +#define HDMI_AHB_DMA_STRADDR0 0x3604 |
| +#define HDMI_AHB_DMA_STRADDR1 0x3605 |
| +#define HDMI_AHB_DMA_STRADDR2 0x3606 |
| +#define HDMI_AHB_DMA_STRADDR3 0x3607 |
| +#define HDMI_AHB_DMA_STPADDR0 0x3608 |
| +#define HDMI_AHB_DMA_STPADDR1 0x3609 |
| +#define HDMI_AHB_DMA_STPADDR2 0x360a |
| +#define HDMI_AHB_DMA_STPADDR3 0x360b |
| +#define HDMI_AHB_DMA_BSTADDR0 0x360c |
| +#define HDMI_AHB_DMA_BSTADDR1 0x360d |
| +#define HDMI_AHB_DMA_BSTADDR2 0x360e |
| +#define HDMI_AHB_DMA_BSTADDR3 0x360f |
| +#define HDMI_AHB_DMA_MBLENGTH0 0x3610 |
| +#define HDMI_AHB_DMA_MBLENGTH1 0x3611 |
| +#define HDMI_AHB_DMA_STAT 0x3612 |
| +#define HDMI_AHB_DMA_INT 0x3613 |
| +#define HDMI_AHB_DMA_MASK 0x3614 |
| +#define HDMI_AHB_DMA_POL 0x3615 |
| +#define HDMI_AHB_DMA_CONF1 0x3616 |
| +#define HDMI_AHB_DMA_BUFFSTAT 0x3617 |
| +#define HDMI_AHB_DMA_BUFFINT 0x3618 |
| +#define HDMI_AHB_DMA_BUFFMASK 0x3619 |
| +#define HDMI_AHB_DMA_BUFFPOL 0x361a |
| + |
| +/* Main Controller Registers */ |
| +#define HDMI_MC_SFRDIV 0x4000 |
| +#define HDMI_MC_CLKDIS 0x4001 |
| +#define HDMI_MC_SWRSTZ 0x4002 |
| +#define HDMI_MC_OPCTRL 0x4003 |
| +#define HDMI_MC_FLOWCTRL 0x4004 |
| +#define HDMI_MC_PHYRSTZ 0x4005 |
| +#define HDMI_MC_LOCKONCLOCK 0x4006 |
| +#define HDMI_MC_HEACPHY_RST 0x4007 |
| + |
| +/* Color Space Converter Registers */ |
| +#define HDMI_CSC_CFG 0x4100 |
| +#define HDMI_CSC_SCALE 0x4101 |
| +#define HDMI_CSC_COEF_A1_MSB 0x4102 |
| +#define HDMI_CSC_COEF_A1_LSB 0x4103 |
| +#define HDMI_CSC_COEF_A2_MSB 0x4104 |
| +#define HDMI_CSC_COEF_A2_LSB 0x4105 |
| +#define HDMI_CSC_COEF_A3_MSB 0x4106 |
| +#define HDMI_CSC_COEF_A3_LSB 0x4107 |
| +#define HDMI_CSC_COEF_A4_MSB 0x4108 |
| +#define HDMI_CSC_COEF_A4_LSB 0x4109 |
| +#define HDMI_CSC_COEF_B1_MSB 0x410A |
| +#define HDMI_CSC_COEF_B1_LSB 0x410B |
| +#define HDMI_CSC_COEF_B2_MSB 0x410C |
| +#define HDMI_CSC_COEF_B2_LSB 0x410D |
| +#define HDMI_CSC_COEF_B3_MSB 0x410E |
| +#define HDMI_CSC_COEF_B3_LSB 0x410F |
| +#define HDMI_CSC_COEF_B4_MSB 0x4110 |
| +#define HDMI_CSC_COEF_B4_LSB 0x4111 |
| +#define HDMI_CSC_COEF_C1_MSB 0x4112 |
| +#define HDMI_CSC_COEF_C1_LSB 0x4113 |
| +#define HDMI_CSC_COEF_C2_MSB 0x4114 |
| +#define HDMI_CSC_COEF_C2_LSB 0x4115 |
| +#define HDMI_CSC_COEF_C3_MSB 0x4116 |
| +#define HDMI_CSC_COEF_C3_LSB 0x4117 |
| +#define HDMI_CSC_COEF_C4_MSB 0x4118 |
| +#define HDMI_CSC_COEF_C4_LSB 0x4119 |
| + |
| +/* HDCP Encryption Engine Registers */ |
| +#define HDMI_A_HDCPCFG0 0x5000 |
| +#define HDMI_A_HDCPCFG1 0x5001 |
| +#define HDMI_A_HDCPOBS0 0x5002 |
| +#define HDMI_A_HDCPOBS1 0x5003 |
| +#define HDMI_A_HDCPOBS2 0x5004 |
| +#define HDMI_A_HDCPOBS3 0x5005 |
| +#define HDMI_A_APIINTCLR 0x5006 |
| +#define HDMI_A_APIINTSTAT 0x5007 |
| +#define HDMI_A_APIINTMSK 0x5008 |
| +#define HDMI_A_VIDPOLCFG 0x5009 |
| +#define HDMI_A_OESSWCFG 0x500A |
| +#define HDMI_A_TIMER1SETUP0 0x500B |
| +#define HDMI_A_TIMER1SETUP1 0x500C |
| +#define HDMI_A_TIMER2SETUP0 0x500D |
| +#define HDMI_A_TIMER2SETUP1 0x500E |
| +#define HDMI_A_100MSCFG 0x500F |
| +#define HDMI_A_2SCFG0 0x5010 |
| +#define HDMI_A_2SCFG1 0x5011 |
| +#define HDMI_A_5SCFG0 0x5012 |
| +#define HDMI_A_5SCFG1 0x5013 |
| +#define HDMI_A_SRMVERLSB 0x5014 |
| +#define HDMI_A_SRMVERMSB 0x5015 |
| +#define HDMI_A_SRMCTRL 0x5016 |
| +#define HDMI_A_SFRSETUP 0x5017 |
| +#define HDMI_A_I2CHSETUP 0x5018 |
| +#define HDMI_A_INTSETUP 0x5019 |
| +#define HDMI_A_PRESETUP 0x501A |
| +#define HDMI_A_SRM_BASE 0x5020 |
| + |
| +/* CEC Engine Registers */ |
| +#define HDMI_CEC_CTRL 0x7D00 |
| +#define HDMI_CEC_STAT 0x7D01 |
| +#define HDMI_CEC_MASK 0x7D02 |
| +#define HDMI_CEC_POLARITY 0x7D03 |
| +#define HDMI_CEC_INT 0x7D04 |
| +#define HDMI_CEC_ADDR_L 0x7D05 |
| +#define HDMI_CEC_ADDR_H 0x7D06 |
| +#define HDMI_CEC_TX_CNT 0x7D07 |
| +#define HDMI_CEC_RX_CNT 0x7D08 |
| +#define HDMI_CEC_TX_DATA0 0x7D10 |
| +#define HDMI_CEC_TX_DATA1 0x7D11 |
| +#define HDMI_CEC_TX_DATA2 0x7D12 |
| +#define HDMI_CEC_TX_DATA3 0x7D13 |
| +#define HDMI_CEC_TX_DATA4 0x7D14 |
| +#define HDMI_CEC_TX_DATA5 0x7D15 |
| +#define HDMI_CEC_TX_DATA6 0x7D16 |
| +#define HDMI_CEC_TX_DATA7 0x7D17 |
| +#define HDMI_CEC_TX_DATA8 0x7D18 |
| +#define HDMI_CEC_TX_DATA9 0x7D19 |
| +#define HDMI_CEC_TX_DATA10 0x7D1a |
| +#define HDMI_CEC_TX_DATA11 0x7D1b |
| +#define HDMI_CEC_TX_DATA12 0x7D1c |
| +#define HDMI_CEC_TX_DATA13 0x7D1d |
| +#define HDMI_CEC_TX_DATA14 0x7D1e |
| +#define HDMI_CEC_TX_DATA15 0x7D1f |
| +#define HDMI_CEC_RX_DATA0 0x7D20 |
| +#define HDMI_CEC_RX_DATA1 0x7D21 |
| +#define HDMI_CEC_RX_DATA2 0x7D22 |
| +#define HDMI_CEC_RX_DATA3 0x7D23 |
| +#define HDMI_CEC_RX_DATA4 0x7D24 |
| +#define HDMI_CEC_RX_DATA5 0x7D25 |
| +#define HDMI_CEC_RX_DATA6 0x7D26 |
| +#define HDMI_CEC_RX_DATA7 0x7D27 |
| +#define HDMI_CEC_RX_DATA8 0x7D28 |
| +#define HDMI_CEC_RX_DATA9 0x7D29 |
| +#define HDMI_CEC_RX_DATA10 0x7D2a |
| +#define HDMI_CEC_RX_DATA11 0x7D2b |
| +#define HDMI_CEC_RX_DATA12 0x7D2c |
| +#define HDMI_CEC_RX_DATA13 0x7D2d |
| +#define HDMI_CEC_RX_DATA14 0x7D2e |
| +#define HDMI_CEC_RX_DATA15 0x7D2f |
| +#define HDMI_CEC_LOCK 0x7D30 |
| +#define HDMI_CEC_WKUPCTRL 0x7D31 |
| + |
| +/* I2C Master Registers (E-DDC) */ |
| +#define HDMI_I2CM_SLAVE 0x7E00 |
| +#define HDMI_I2CM_ADDRESS 0x7E01 |
| +#define HDMI_I2CM_DATAO 0x7E02 |
| +#define HDMI_I2CM_DATAI 0x7E03 |
| +#define HDMI_I2CM_OPERATION 0x7E04 |
| +#define HDMI_I2CM_INT 0x7E05 |
| +#define HDMI_I2CM_CTLINT 0x7E06 |
| +#define HDMI_I2CM_DIV 0x7E07 |
| +#define HDMI_I2CM_SEGADDR 0x7E08 |
| +#define HDMI_I2CM_SOFTRSTZ 0x7E09 |
| +#define HDMI_I2CM_SEGPTR 0x7E0A |
| +#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B |
| +#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C |
| +#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D |
| +#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E |
| +#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F |
| +#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10 |
| +#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11 |
| +#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12 |
| + |
| +enum { |
| +/* PRODUCT_ID0 field values */ |
| + HDMI_PRODUCT_ID0_HDMI_TX = 0xa0, |
| + |
| +/* PRODUCT_ID1 field values */ |
| + HDMI_PRODUCT_ID1_HDCP = 0xc0, |
| + HDMI_PRODUCT_ID1_HDMI_RX = 0x02, |
| + HDMI_PRODUCT_ID1_HDMI_TX = 0x01, |
| + |
| +/* CONFIG0_ID field values */ |
| + HDMI_CONFIG0_I2S = 0x10, |
| + |
| +/* CONFIG1_ID field values */ |
| + HDMI_CONFIG1_AHB = 0x01, |
| + |
| +/* CONFIG3_ID field values */ |
| + HDMI_CONFIG3_AHBAUDDMA = 0x02, |
| + HDMI_CONFIG3_GPAUD = 0x01, |
| + |
| +/* IH_FC_INT2 field values */ |
| + HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03, |
| + HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| + HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| + |
| +/* IH_FC_STAT2 field values */ |
| + HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03, |
| + HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| + HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| + |
| +/* IH_PHY_STAT0 field values */ |
| + HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20, |
| + HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10, |
| + HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8, |
| + HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4, |
| + HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2, |
| + HDMI_IH_PHY_STAT0_HPD = 0x1, |
| + |
| +/* IH_I2CM_STAT0 and IH_MUTE_I2CM_STAT0 field values */ |
| + HDMI_IH_I2CM_STAT0_DONE = 0x2, |
| + HDMI_IH_I2CM_STAT0_ERROR = 0x1, |
| + |
| +/* IH_MUTE_I2CMPHY_STAT0 field values */ |
| + HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2, |
| + HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1, |
| + |
| +/* IH_AHBDMAAUD_STAT0 field values */ |
| + HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20, |
| + HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10, |
| + HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08, |
| + HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04, |
| + HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02, |
| + HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01, |
| + |
| +/* IH_MUTE_FC_STAT2 field values */ |
| + HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03, |
| + HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| + HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| + |
| +/* IH_MUTE_AHBDMAAUD_STAT0 field values */ |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20, |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10, |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08, |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04, |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02, |
| + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01, |
| + |
| +/* IH_MUTE field values */ |
| + HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2, |
| + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1, |
| + |
| +/* TX_INVID0 field values */ |
| + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80, |
| + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80, |
| + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00, |
| + HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F, |
| + HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0, |
| + |
| +/* TX_INSTUFFING field values */ |
| + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4, |
| + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4, |
| + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0, |
| + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2, |
| + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2, |
| + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0, |
| + HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1, |
| + HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1, |
| + HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0, |
| + |
| +/* VP_PR_CD field values */ |
| + HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0, |
| + HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4, |
| + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F, |
| + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0, |
| + |
| +/* VP_STUFF field values */ |
| + HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20, |
| + HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5, |
| + HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10, |
| + HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4, |
| + HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8, |
| + HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3, |
| + HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4, |
| + HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4, |
| + HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0, |
| + HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2, |
| + HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2, |
| + HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0, |
| + HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1, |
| + HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1, |
| + HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0, |
| + |
| +/* VP_CONF field values */ |
| + HDMI_VP_CONF_BYPASS_EN_MASK = 0x40, |
| + HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40, |
| + HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00, |
| + HDMI_VP_CONF_PP_EN_ENMASK = 0x20, |
| + HDMI_VP_CONF_PP_EN_ENABLE = 0x20, |
| + HDMI_VP_CONF_PP_EN_DISABLE = 0x00, |
| + HDMI_VP_CONF_PR_EN_MASK = 0x10, |
| + HDMI_VP_CONF_PR_EN_ENABLE = 0x10, |
| + HDMI_VP_CONF_PR_EN_DISABLE = 0x00, |
| + HDMI_VP_CONF_YCC422_EN_MASK = 0x8, |
| + HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8, |
| + HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0, |
| + HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4, |
| + HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4, |
| + HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0, |
| + HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3, |
| + HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3, |
| + HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1, |
| + HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0, |
| + |
| +/* VP_REMAP field values */ |
| + HDMI_VP_REMAP_MASK = 0x3, |
| + HDMI_VP_REMAP_YCC422_24bit = 0x2, |
| + HDMI_VP_REMAP_YCC422_20bit = 0x1, |
| + HDMI_VP_REMAP_YCC422_16bit = 0x0, |
| + |
| +/* FC_INVIDCONF field values */ |
| + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80, |
| + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80, |
| + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00, |
| + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40, |
| + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40, |
| + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00, |
| + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20, |
| + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20, |
| + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00, |
| + HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10, |
| + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10, |
| + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00, |
| + HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8, |
| + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8, |
| + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0, |
| + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2, |
| + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2, |
| + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0, |
| + HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1, |
| + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1, |
| + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0, |
| + |
| +/* FC_AUDICONF0 field values */ |
| + HDMI_FC_AUDICONF0_CC_OFFSET = 4, |
| + HDMI_FC_AUDICONF0_CC_MASK = 0x70, |
| + HDMI_FC_AUDICONF0_CT_OFFSET = 0, |
| + HDMI_FC_AUDICONF0_CT_MASK = 0xF, |
| + |
| +/* FC_AUDICONF1 field values */ |
| + HDMI_FC_AUDICONF1_SS_OFFSET = 3, |
| + HDMI_FC_AUDICONF1_SS_MASK = 0x18, |
| + HDMI_FC_AUDICONF1_SF_OFFSET = 0, |
| + HDMI_FC_AUDICONF1_SF_MASK = 0x7, |
| + |
| +/* FC_AUDICONF3 field values */ |
| + HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5, |
| + HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60, |
| + HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4, |
| + HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10, |
| + HDMI_FC_AUDICONF3_LSV_OFFSET = 0, |
| + HDMI_FC_AUDICONF3_LSV_MASK = 0xF, |
| + |
| +/* FC_AUDSCHNLS0 field values */ |
| + HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4, |
| + HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30, |
| + HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0, |
| + HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01, |
| + |
| +/* FC_AUDSCHNLS3-6 field values */ |
| + HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0, |
| + HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f, |
| + HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4, |
| + HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0, |
| + HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0, |
| + HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f, |
| + HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4, |
| + HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0, |
| + |
| + HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0, |
| + HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f, |
| + HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4, |
| + HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0, |
| + HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0, |
| + HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f, |
| + HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4, |
| + HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0, |
| + |
| +/* HDMI_FC_AUDSCHNLS7 field values */ |
| + HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4, |
| + HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30, |
| + |
| +/* HDMI_FC_AUDSCHNLS8 field values */ |
| + HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0, |
| + HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4, |
| + HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f, |
| + HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0, |
| + |
| +/* FC_AUDSCONF field values */ |
| + HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0, |
| + HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4, |
| + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1, |
| + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0, |
| + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1, |
| + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0, |
| + |
| +/* FC_STAT2 field values */ |
| + HDMI_FC_STAT2_OVERFLOW_MASK = 0x03, |
| + HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| + HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| + |
| +/* FC_INT2 field values */ |
| + HDMI_FC_INT2_OVERFLOW_MASK = 0x03, |
| + HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02, |
| + HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| + |
| +/* FC_MASK2 field values */ |
| + HDMI_FC_MASK2_OVERFLOW_MASK = 0x03, |
| + HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02, |
| + HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01, |
| + |
| +/* FC_PRCONF field values */ |
| + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0, |
| + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4, |
| + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F, |
| + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0, |
| + |
| +/* FC_AVICONF0-FC_AVICONF3 field values */ |
| + HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03, |
| + HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00, |
| + HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01, |
| + HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02, |
| + HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40, |
| + HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40, |
| + HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00, |
| + HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C, |
| + HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00, |
| + HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04, |
| + HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08, |
| + HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C, |
| + HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30, |
| + HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10, |
| + HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20, |
| + HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00, |
| + |
| + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F, |
| + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08, |
| + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09, |
| + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A, |
| + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B, |
| + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30, |
| + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00, |
| + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10, |
| + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20, |
| + HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0, |
| + HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00, |
| + HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40, |
| + HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80, |
| + HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0, |
| + |
| + HDMI_FC_AVICONF2_SCALING_MASK = 0x03, |
| + HDMI_FC_AVICONF2_SCALING_NONE = 0x00, |
| + HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01, |
| + HDMI_FC_AVICONF2_SCALING_VERT = 0x02, |
| + HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03, |
| + HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C, |
| + HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00, |
| + HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04, |
| + HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08, |
| + HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70, |
| + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00, |
| + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10, |
| + HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20, |
| + HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30, |
| + HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40, |
| + HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80, |
| + HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00, |
| + HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80, |
| + |
| + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03, |
| + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00, |
| + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01, |
| + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02, |
| + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03, |
| + HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C, |
| + HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00, |
| + HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04, |
| + |
| +/* FC_DBGFORCE field values */ |
| + HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, |
| + HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, |
| + |
| +/* PHY_CONF0 field values */ |
| + HDMI_PHY_CONF0_PDZ_MASK = 0x80, |
| + HDMI_PHY_CONF0_PDZ_OFFSET = 7, |
| + HDMI_PHY_CONF0_ENTMDS_MASK = 0x40, |
| + HDMI_PHY_CONF0_ENTMDS_OFFSET = 6, |
| + HDMI_PHY_CONF0_SVSRET_MASK = 0x20, |
| + HDMI_PHY_CONF0_SVSRET_OFFSET = 5, |
| + HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10, |
| + HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4, |
| + HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8, |
| + HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3, |
| + HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4, |
| + HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2, |
| + HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2, |
| + HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1, |
| + HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1, |
| + HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0, |
| + |
| +/* PHY_TST0 field values */ |
| + HDMI_PHY_TST0_TSTCLR_MASK = 0x20, |
| + HDMI_PHY_TST0_TSTCLR_OFFSET = 5, |
| + HDMI_PHY_TST0_TSTEN_MASK = 0x10, |
| + HDMI_PHY_TST0_TSTEN_OFFSET = 4, |
| + HDMI_PHY_TST0_TSTCLK_MASK = 0x1, |
| + HDMI_PHY_TST0_TSTCLK_OFFSET = 0, |
| + |
| +/* PHY_STAT0 field values */ |
| + HDMI_PHY_RX_SENSE3 = 0x80, |
| + HDMI_PHY_RX_SENSE2 = 0x40, |
| + HDMI_PHY_RX_SENSE1 = 0x20, |
| + HDMI_PHY_RX_SENSE0 = 0x10, |
| + HDMI_PHY_HPD = 0x02, |
| + HDMI_PHY_TX_PHY_LOCK = 0x01, |
| + |
| +/* PHY_I2CM_SLAVE_ADDR field values */ |
| + HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69, |
| + HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49, |
| + |
| +/* PHY_I2CM_OPERATION_ADDR field values */ |
| + HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10, |
| + HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1, |
| + |
| +/* HDMI_PHY_I2CM_INT_ADDR */ |
| + HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08, |
| + HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04, |
| + |
| +/* HDMI_PHY_I2CM_CTLINT_ADDR */ |
| + HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80, |
| + HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40, |
| + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08, |
| + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04, |
| + |
| +/* AUD_CONF0 field values */ |
| + HDMI_AUD_CONF0_SW_RESET = 0x80, |
| + HDMI_AUD_CONF0_I2S_ALL_ENABLE = 0x2F, |
| + |
| +/* AUD_CONF1 field values */ |
| + HDMI_AUD_CONF1_MODE_I2S = 0x00, |
| + HDMI_AUD_CONF1_MODE_RIGHT_J = 0x02, |
| + HDMI_AUD_CONF1_MODE_LEFT_J = 0x04, |
| + HDMI_AUD_CONF1_WIDTH_16 = 0x10, |
| + HDMI_AUD_CONF1_WIDTH_24 = 0x18, |
| + |
| +/* AUD_CTS3 field values */ |
| + HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5, |
| + HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0, |
| + HDMI_AUD_CTS3_N_SHIFT_1 = 0, |
| + HDMI_AUD_CTS3_N_SHIFT_16 = 0x20, |
| + HDMI_AUD_CTS3_N_SHIFT_32 = 0x40, |
| + HDMI_AUD_CTS3_N_SHIFT_64 = 0x60, |
| + HDMI_AUD_CTS3_N_SHIFT_128 = 0x80, |
| + HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0, |
| + /* note that the CTS3 MANUAL bit has been removed |
| + from our part. Can't set it, will read as 0. */ |
| + HDMI_AUD_CTS3_CTS_MANUAL = 0x10, |
| + HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f, |
| + |
| +/* HDMI_AUD_INPUTCLKFS field values */ |
| + HDMI_AUD_INPUTCLKFS_128FS = 0, |
| + HDMI_AUD_INPUTCLKFS_256FS = 1, |
| + HDMI_AUD_INPUTCLKFS_512FS = 2, |
| + HDMI_AUD_INPUTCLKFS_64FS = 4, |
| + |
| +/* AHB_DMA_CONF0 field values */ |
| + HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7, |
| + HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80, |
| + HDMI_AHB_DMA_CONF0_HBR = 0x10, |
| + HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3, |
| + HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08, |
| + HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1, |
| + HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06, |
| + HDMI_AHB_DMA_CONF0_INCR4 = 0x0, |
| + HDMI_AHB_DMA_CONF0_INCR8 = 0x2, |
| + HDMI_AHB_DMA_CONF0_INCR16 = 0x4, |
| + HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1, |
| + |
| +/* HDMI_AHB_DMA_START field values */ |
| + HDMI_AHB_DMA_START_START_OFFSET = 0, |
| + HDMI_AHB_DMA_START_START_MASK = 0x01, |
| + |
| +/* HDMI_AHB_DMA_STOP field values */ |
| + HDMI_AHB_DMA_STOP_STOP_OFFSET = 0, |
| + HDMI_AHB_DMA_STOP_STOP_MASK = 0x01, |
| + |
| +/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */ |
| + HDMI_AHB_DMA_DONE = 0x80, |
| + HDMI_AHB_DMA_RETRY_SPLIT = 0x40, |
| + HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20, |
| + HDMI_AHB_DMA_ERROR = 0x10, |
| + HDMI_AHB_DMA_FIFO_THREMPTY = 0x04, |
| + HDMI_AHB_DMA_FIFO_FULL = 0x02, |
| + HDMI_AHB_DMA_FIFO_EMPTY = 0x01, |
| + |
| +/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT,AHB_DMA_BUFFMASK,AHB_DMA_BUFFPOL values */ |
| + HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02, |
| + HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01, |
| + |
| +/* MC_CLKDIS field values */ |
| + HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40, |
| + HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20, |
| + HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10, |
| + HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8, |
| + HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4, |
| + HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2, |
| + HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1, |
| + |
| +/* MC_SWRSTZ field values */ |
| + HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02, |
| + |
| +/* MC_FLOWCTRL field values */ |
| + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1, |
| + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1, |
| + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0, |
| + |
| +/* MC_PHYRSTZ field values */ |
| + HDMI_MC_PHYRSTZ_PHYRSTZ = 0x01, |
| + |
| +/* MC_HEACPHY_RST field values */ |
| + HDMI_MC_HEACPHY_RST_ASSERT = 0x1, |
| + HDMI_MC_HEACPHY_RST_DEASSERT = 0x0, |
| + |
| +/* CSC_CFG field values */ |
| + HDMI_CSC_CFG_INTMODE_MASK = 0x30, |
| + HDMI_CSC_CFG_INTMODE_OFFSET = 4, |
| + HDMI_CSC_CFG_INTMODE_DISABLE = 0x00, |
| + HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10, |
| + HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20, |
| + HDMI_CSC_CFG_DECMODE_MASK = 0x3, |
| + HDMI_CSC_CFG_DECMODE_OFFSET = 0, |
| + HDMI_CSC_CFG_DECMODE_DISABLE = 0x0, |
| + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1, |
| + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2, |
| + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3, |
| + |
| +/* CSC_SCALE field values */ |
| + HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0, |
| + HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00, |
| + HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50, |
| + HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60, |
| + HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70, |
| + HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03, |
| + |
| +/* A_HDCPCFG0 field values */ |
| + HDMI_A_HDCPCFG0_ELVENA_MASK = 0x80, |
| + HDMI_A_HDCPCFG0_ELVENA_ENABLE = 0x80, |
| + HDMI_A_HDCPCFG0_ELVENA_DISABLE = 0x00, |
| + HDMI_A_HDCPCFG0_I2CFASTMODE_MASK = 0x40, |
| + HDMI_A_HDCPCFG0_I2CFASTMODE_ENABLE = 0x40, |
| + HDMI_A_HDCPCFG0_I2CFASTMODE_DISABLE = 0x00, |
| + HDMI_A_HDCPCFG0_BYPENCRYPTION_MASK = 0x20, |
| + HDMI_A_HDCPCFG0_BYPENCRYPTION_ENABLE = 0x20, |
| + HDMI_A_HDCPCFG0_BYPENCRYPTION_DISABLE = 0x00, |
| + HDMI_A_HDCPCFG0_SYNCRICHECK_MASK = 0x10, |
| + HDMI_A_HDCPCFG0_SYNCRICHECK_ENABLE = 0x10, |
| + HDMI_A_HDCPCFG0_SYNCRICHECK_DISABLE = 0x00, |
| + HDMI_A_HDCPCFG0_AVMUTE_MASK = 0x8, |
| + HDMI_A_HDCPCFG0_AVMUTE_ENABLE = 0x8, |
| + HDMI_A_HDCPCFG0_AVMUTE_DISABLE = 0x0, |
| + HDMI_A_HDCPCFG0_RXDETECT_MASK = 0x4, |
| + HDMI_A_HDCPCFG0_RXDETECT_ENABLE = 0x4, |
| + HDMI_A_HDCPCFG0_RXDETECT_DISABLE = 0x0, |
| + HDMI_A_HDCPCFG0_EN11FEATURE_MASK = 0x2, |
| + HDMI_A_HDCPCFG0_EN11FEATURE_ENABLE = 0x2, |
| + HDMI_A_HDCPCFG0_EN11FEATURE_DISABLE = 0x0, |
| + HDMI_A_HDCPCFG0_HDMIDVI_MASK = 0x1, |
| + HDMI_A_HDCPCFG0_HDMIDVI_HDMI = 0x1, |
| + HDMI_A_HDCPCFG0_HDMIDVI_DVI = 0x0, |
| + |
| +/* A_HDCPCFG1 field values */ |
| + HDMI_A_HDCPCFG1_DISSHA1CHECK_MASK = 0x8, |
| + HDMI_A_HDCPCFG1_DISSHA1CHECK_DISABLE = 0x8, |
| + HDMI_A_HDCPCFG1_DISSHA1CHECK_ENABLE = 0x0, |
| + HDMI_A_HDCPCFG1_PH2UPSHFTENC_MASK = 0x4, |
| + HDMI_A_HDCPCFG1_PH2UPSHFTENC_ENABLE = 0x4, |
| + HDMI_A_HDCPCFG1_PH2UPSHFTENC_DISABLE = 0x0, |
| + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK = 0x2, |
| + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE = 0x2, |
| + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_ENABLE = 0x0, |
| + HDMI_A_HDCPCFG1_SWRESET_MASK = 0x1, |
| + HDMI_A_HDCPCFG1_SWRESET_ASSERT = 0x0, |
| + |
| +/* A_VIDPOLCFG field values */ |
| + HDMI_A_VIDPOLCFG_UNENCRYPTCONF_MASK = 0x60, |
| + HDMI_A_VIDPOLCFG_UNENCRYPTCONF_OFFSET = 5, |
| + HDMI_A_VIDPOLCFG_DATAENPOL_MASK = 0x10, |
| + HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH = 0x10, |
| + HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW = 0x0, |
| + HDMI_A_VIDPOLCFG_VSYNCPOL_MASK = 0x8, |
| + HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_HIGH = 0x8, |
| + HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_LOW = 0x0, |
| + HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2, |
| + HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2, |
| + HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0, |
| + |
| +/* I2CM_OPERATION field values */ |
| + HDMI_I2CM_OPERATION_WRITE = 0x10, |
| + HDMI_I2CM_OPERATION_READ_EXT = 0x2, |
| + HDMI_I2CM_OPERATION_READ = 0x1, |
| + |
| +/* I2CM_INT field values */ |
| + HDMI_I2CM_INT_DONE_POL = 0x8, |
| + HDMI_I2CM_INT_DONE_MASK = 0x4, |
| + |
| +/* I2CM_CTLINT field values */ |
| + HDMI_I2CM_CTLINT_NAC_POL = 0x80, |
| + HDMI_I2CM_CTLINT_NAC_MASK = 0x40, |
| + HDMI_I2CM_CTLINT_ARB_POL = 0x8, |
| + HDMI_I2CM_CTLINT_ARB_MASK = 0x4, |
| +}; |
| + |
| +/* |
| + * HDMI 3D TX PHY registers |
| + */ |
| +#define HDMI_3D_TX_PHY_PWRCTRL 0x00 |
| +#define HDMI_3D_TX_PHY_SERDIVCTRL 0x01 |
| +#define HDMI_3D_TX_PHY_SERCKCTRL 0x02 |
| +#define HDMI_3D_TX_PHY_SERCKKILLCTRL 0x03 |
| +#define HDMI_3D_TX_PHY_TXRESCTRL 0x04 |
| +#define HDMI_3D_TX_PHY_CKCALCTRL 0x05 |
| +#define HDMI_3D_TX_PHY_CPCE_CTRL 0x06 |
| +#define HDMI_3D_TX_PHY_TXCLKMEASCTRL 0x07 |
| +#define HDMI_3D_TX_PHY_TXMEASCTRL 0x08 |
| +#define HDMI_3D_TX_PHY_CKSYMTXCTRL 0x09 |
| +#define HDMI_3D_TX_PHY_CMPSEQCTRL 0x0a |
| +#define HDMI_3D_TX_PHY_CMPPWRCTRL 0x0b |
| +#define HDMI_3D_TX_PHY_CMPMODECTRL 0x0c |
| +#define HDMI_3D_TX_PHY_MEASCTRL 0x0d |
| +#define HDMI_3D_TX_PHY_VLEVCTRL 0x0e |
| +#define HDMI_3D_TX_PHY_D2ACTRL 0x0f |
| +#define HDMI_3D_TX_PHY_CURRCTRL 0x10 |
| +#define HDMI_3D_TX_PHY_DRVANACTRL 0x11 |
| +#define HDMI_3D_TX_PHY_PLLMEASCTRL 0x12 |
| +#define HDMI_3D_TX_PHY_PLLPHBYCTRL 0x13 |
| +#define HDMI_3D_TX_PHY_GRP_CTRL 0x14 |
| +#define HDMI_3D_TX_PHY_GMPCTRL 0x15 |
| +#define HDMI_3D_TX_PHY_MPLLMEASCTRL 0x16 |
| +#define HDMI_3D_TX_PHY_MSM_CTRL 0x17 |
| +#define HDMI_3D_TX_PHY_SCRPB_STATUS 0x18 |
| +#define HDMI_3D_TX_PHY_TXTERM 0x19 |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL 0x1a |
| +#define HDMI_3D_TX_PHY_PATTERNGEN 0x1b |
| +#define HDMI_3D_TX_PHY_SDCAP_MODE 0x1c |
| +#define HDMI_3D_TX_PHY_SCOPEMODE 0x1d |
| +#define HDMI_3D_TX_PHY_DIGTXMODE 0x1e |
| +#define HDMI_3D_TX_PHY_STR_STATUS 0x1f |
| +#define HDMI_3D_TX_PHY_SCOPECNT0 0x20 |
| +#define HDMI_3D_TX_PHY_SCOPECNT1 0x21 |
| +#define HDMI_3D_TX_PHY_SCOPECNT2 0x22 |
| +#define HDMI_3D_TX_PHY_SCOPECNTCLK 0x23 |
| +#define HDMI_3D_TX_PHY_SCOPESAMPLE 0x24 |
| +#define HDMI_3D_TX_PHY_SCOPECNTMSB01 0x25 |
| +#define HDMI_3D_TX_PHY_SCOPECNTMSB2CK 0x26 |
| + |
| +/* HDMI_3D_TX_PHY_CKCALCTRL values */ |
| +#define HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE BIT(15) |
| + |
| +/* HDMI_3D_TX_PHY_MSM_CTRL values */ |
| +#define HDMI_3D_TX_PHY_MSM_CTRL_MPLL_PH_SEL_CK BIT(13) |
| +#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_CLK_REF_MPLL (0 << 1) |
| +#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_OFF (1 << 1) |
| +#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_PCLK (2 << 1) |
| +#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK (3 << 1) |
| +#define HDMI_3D_TX_PHY_MSM_CTRL_SCOPE_CK_SEL BIT(0) |
| + |
| +/* HDMI_3D_TX_PHY_PTRPT_ENBL values */ |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_OVERRIDE BIT(15) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT2 BIT(8) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT1 BIT(7) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT0 BIT(6) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_CK_REF_ENB BIT(5) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_RCAL_ENB BIT(4) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_CLK_ALIGN_ENB BIT(3) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_READY BIT(2) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_CKO_WORD_ENB BIT(1) |
| +#define HDMI_3D_TX_PHY_PTRPT_ENBL_REFCLK_ENB BIT(0) |
| + |
| +#endif /* __DW_HDMI_H__ */ |