提交 f5bab222 编写于 作者: T Tomi Valkeinen

OMAPDSS: HDMI: Add OMAP5 HDMI support

This adds a new driver to omapdss for OMAP5 HDMI. However, the new
driver uses common HDMI files which are shared with OMAP4 HDMI driver.

OMAP5 HDMI has a different HDMI core IP compared to OMAP4, but has very
similar PLL and PHY IPs which can be handled with common code.
Signed-off-by: NTomi Valkeinen <tomi.valkeinen@ti.com>
上级 2d64b1b3
......@@ -72,6 +72,19 @@ config OMAP4_DSS_HDMI
config OMAP4_DSS_HDMI_AUDIO
bool
config OMAP5_DSS_HDMI
bool "HDMI support for OMAP5"
default n
select OMAP2_DSS_HDMI_COMMON
help
HDMI Interface for OMAP5 and similar cores. This adds the High
Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI
specification.
config OMAP5_DSS_HDMI_AUDIO
depends on OMAP5_DSS_HDMI
bool
config OMAP2_DSS_SDI
bool "SDI support"
default n
......
......@@ -13,4 +13,5 @@ omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP2_DSS_HDMI_COMMON) += hdmi_common.o hdmi_wp.o hdmi_pll.o \
hdmi_phy.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi4_core.o
omapdss-$(CONFIG_OMAP5_DSS_HDMI) += hdmi5.o hdmi5_core.o
ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
......@@ -268,6 +268,9 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
#ifdef CONFIG_OMAP4_DSS_HDMI
hdmi4_init_platform_driver,
#endif
#ifdef CONFIG_OMAP5_DSS_HDMI
hdmi5_init_platform_driver,
#endif
};
static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
......@@ -289,6 +292,9 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
#ifdef CONFIG_OMAP4_DSS_HDMI
hdmi4_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP5_DSS_HDMI
hdmi5_uninit_platform_driver,
#endif
};
static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
......
......@@ -419,6 +419,9 @@ void venc_uninit_platform_driver(void) __exit;
int hdmi4_init_platform_driver(void) __init;
void hdmi4_uninit_platform_driver(void) __exit;
int hdmi5_init_platform_driver(void) __init;
void hdmi5_uninit_platform_driver(void) __exit;
/* RFBI */
int rfbi_init_platform_driver(void) __init;
void rfbi_uninit_platform_driver(void) __exit;
......
......@@ -431,7 +431,7 @@ struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing);
int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
struct hdmi_phy_data *phy);
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts);
int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable);
int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable);
......
/*
* HDMI driver for OMAP5
*
* Copyright (C) 2014 Texas Instruments Incorporated
*
* Authors:
* Yong Zhi
* Mythri pk
* Archit Taneja <archit@ti.com>
* Tomi Valkeinen <tomi.valkeinen@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define DSS_SUBSYS_NAME "HDMI"
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <video/omapdss.h>
#include "hdmi5_core.h"
#include "dss.h"
#include "dss_features.h"
static struct {
struct mutex lock;
struct platform_device *pdev;
struct hdmi_wp_data wp;
struct hdmi_pll_data pll;
struct hdmi_phy_data phy;
struct hdmi_core_data core;
struct hdmi_config cfg;
struct clk *sys_clk;
struct regulator *vdda_reg;
bool core_enabled;
struct omap_dss_device output;
} hdmi;
static int hdmi_runtime_get(void)
{
int r;
DSSDBG("hdmi_runtime_get\n");
r = pm_runtime_get_sync(&hdmi.pdev->dev);
WARN_ON(r < 0);
if (r < 0)
return r;
return 0;
}
static void hdmi_runtime_put(void)
{
int r;
DSSDBG("hdmi_runtime_put\n");
r = pm_runtime_put_sync(&hdmi.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
static irqreturn_t hdmi_irq_handler(int irq, void *data)
{
struct hdmi_wp_data *wp = data;
u32 irqstatus;
irqstatus = hdmi_wp_get_irqstatus(wp);
hdmi_wp_set_irqstatus(wp, irqstatus);
if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
u32 v;
/*
* If we get both connect and disconnect interrupts at the same
* time, turn off the PHY, clear interrupts, and restart, which
* raises connect interrupt if a cable is connected, or nothing
* if cable is not connected.
*/
hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
/*
* We always get bogus CONNECT & DISCONNECT interrupts when
* setting the PHY to LDOON. To ignore those, we force the RXDET
* line to 0 until the PHY power state has been changed.
*/
v = hdmi_read_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL);
v = FLD_MOD(v, 1, 15, 15); /* FORCE_RXDET_HIGH */
v = FLD_MOD(v, 0, 14, 7); /* RXDET_LINE */
hdmi_write_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, v);
hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
HDMI_IRQ_LINK_DISCONNECT);
hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
REG_FLD_MOD(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, 0, 15, 15);
} else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
} else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
}
return IRQ_HANDLED;
}
static int hdmi_init_regulator(void)
{
int r;
struct regulator *reg;
if (hdmi.vdda_reg != NULL)
return 0;
reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
if (IS_ERR(reg)) {
DSSERR("can't get VDDA regulator\n");
return PTR_ERR(reg);
}
if (regulator_can_change_voltage(reg)) {
r = regulator_set_voltage(reg, 1800000, 1800000);
if (r) {
devm_regulator_put(reg);
DSSWARN("can't set the regulator voltage\n");
return r;
}
}
hdmi.vdda_reg = reg;
return 0;
}
static int hdmi_power_on_core(struct omap_dss_device *dssdev)
{
int r;
r = regulator_enable(hdmi.vdda_reg);
if (r)
return r;
r = hdmi_runtime_get();
if (r)
goto err_runtime_get;
/* Make selection of HDMI in DSS */
dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
hdmi.core_enabled = true;
return 0;
err_runtime_get:
regulator_disable(hdmi.vdda_reg);
return r;
}
static void hdmi_power_off_core(struct omap_dss_device *dssdev)
{
hdmi.core_enabled = false;
hdmi_runtime_put();
regulator_disable(hdmi.vdda_reg);
}
static int hdmi_power_on_full(struct omap_dss_device *dssdev)
{
int r;
struct omap_video_timings *p;
struct omap_overlay_manager *mgr = hdmi.output.manager;
unsigned long phy;
r = hdmi_power_on_core(dssdev);
if (r)
return r;
p = &hdmi.cfg.timings;
DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
/* the functions below use kHz pixel clock. TODO: change to Hz */
phy = p->pixelclock / 1000;
hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
/* disable and clear irqs */
hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
hdmi_wp_set_irqstatus(&hdmi.wp,
hdmi_wp_get_irqstatus(&hdmi.wp));
/* config the PLL and PHY hdmi_set_pll_pwrfirst */
r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
if (r) {
DSSDBG("Failed to lock PLL\n");
goto err_pll_enable;
}
r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg);
if (r) {
DSSDBG("Failed to start PHY\n");
goto err_phy_cfg;
}
r = hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_LDOON);
if (r)
goto err_phy_pwr;
hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
/* bypass TV gamma table */
dispc_enable_gamma_table(0);
/* tv size */
dss_mgr_set_timings(mgr, p);
r = hdmi_wp_video_start(&hdmi.wp);
if (r)
goto err_vid_enable;
r = dss_mgr_enable(mgr);
if (r)
goto err_mgr_enable;
hdmi_wp_set_irqenable(&hdmi.wp,
HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
return 0;
err_mgr_enable:
hdmi_wp_video_stop(&hdmi.wp);
err_vid_enable:
hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
err_phy_pwr:
err_phy_cfg:
hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
err_pll_enable:
hdmi_power_off_core(dssdev);
return -EIO;
}
static void hdmi_power_off_full(struct omap_dss_device *dssdev)
{
struct omap_overlay_manager *mgr = hdmi.output.manager;
hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
dss_mgr_disable(mgr);
hdmi_wp_video_stop(&hdmi.wp);
hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
hdmi_power_off_core(dssdev);
}
static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct omap_dss_device *out = &hdmi.output;
if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
return -EINVAL;
return 0;
}
static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct hdmi_cm cm;
const struct hdmi_config *t;
mutex_lock(&hdmi.lock);
cm = hdmi_get_code(timings);
hdmi.cfg.cm = cm;
t = hdmi_get_timings(cm.mode, cm.code);
if (t != NULL) {
hdmi.cfg = *t;
dispc_set_tv_pclk(t->timings.pixelclock);
} else {
hdmi.cfg.timings = *timings;
hdmi.cfg.cm.code = 0;
hdmi.cfg.cm.mode = HDMI_DVI;
dispc_set_tv_pclk(timings->pixelclock);
}
DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ?
"DVI" : "HDMI", hdmi.cfg.cm.code);
mutex_unlock(&hdmi.lock);
}
static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
const struct hdmi_config *cfg;
struct hdmi_cm cm = hdmi.cfg.cm;
cfg = hdmi_get_timings(cm.mode, cm.code);
if (cfg == NULL)
cfg = hdmi_default_timing();
memcpy(timings, &cfg->timings, sizeof(cfg->timings));
}
static void hdmi_dump_regs(struct seq_file *s)
{
mutex_lock(&hdmi.lock);
if (hdmi_runtime_get()) {
mutex_unlock(&hdmi.lock);
return;
}
hdmi_wp_dump(&hdmi.wp, s);
hdmi_pll_dump(&hdmi.pll, s);
hdmi_phy_dump(&hdmi.phy, s);
hdmi5_core_dump(&hdmi.core, s);
hdmi_runtime_put();
mutex_unlock(&hdmi.lock);
}
static int read_edid(u8 *buf, int len)
{
int r;
int idlemode;
mutex_lock(&hdmi.lock);
r = hdmi_runtime_get();
BUG_ON(r);
idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
/* No-idle mode */
REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
r = hdmi5_read_edid(&hdmi.core, buf, len);
REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
hdmi_runtime_put();
mutex_unlock(&hdmi.lock);
return r;
}
static int hdmi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &hdmi.output;
int r = 0;
DSSDBG("ENTER hdmi_display_enable\n");
mutex_lock(&hdmi.lock);
if (out == NULL || out->manager == NULL) {
DSSERR("failed to enable display: no output/manager\n");
r = -ENODEV;
goto err0;
}
r = hdmi_power_on_full(dssdev);
if (r) {
DSSERR("failed to power on device\n");
goto err0;
}
mutex_unlock(&hdmi.lock);
return 0;
err0:
mutex_unlock(&hdmi.lock);
return r;
}
static void hdmi_display_disable(struct omap_dss_device *dssdev)
{
DSSDBG("Enter hdmi_display_disable\n");
mutex_lock(&hdmi.lock);
hdmi_power_off_full(dssdev);
mutex_unlock(&hdmi.lock);
}
static int hdmi_core_enable(struct omap_dss_device *dssdev)
{
int r = 0;
DSSDBG("ENTER omapdss_hdmi_core_enable\n");
mutex_lock(&hdmi.lock);
r = hdmi_power_on_core(dssdev);
if (r) {
DSSERR("failed to power on device\n");
goto err0;
}
mutex_unlock(&hdmi.lock);
return 0;
err0:
mutex_unlock(&hdmi.lock);
return r;
}
static void hdmi_core_disable(struct omap_dss_device *dssdev)
{
DSSDBG("Enter omapdss_hdmi_core_disable\n");
mutex_lock(&hdmi.lock);
hdmi_power_off_core(dssdev);
mutex_unlock(&hdmi.lock);
}
static int hdmi_get_clocks(struct platform_device *pdev)
{
struct clk *clk;
clk = devm_clk_get(&pdev->dev, "sys_clk");
if (IS_ERR(clk)) {
DSSERR("can't get sys_clk\n");
return PTR_ERR(clk);
}
hdmi.sys_clk = clk;
return 0;
}
static int hdmi_connect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
struct omap_overlay_manager *mgr;
int r;
r = hdmi_init_regulator();
if (r)
return r;
mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
if (!mgr)
return -ENODEV;
r = dss_mgr_connect(mgr, dssdev);
if (r)
return r;
r = omapdss_output_set_device(dssdev, dst);
if (r) {
DSSERR("failed to connect output to new device: %s\n",
dst->name);
dss_mgr_disconnect(mgr, dssdev);
return r;
}
return 0;
}
static void hdmi_disconnect(struct omap_dss_device *dssdev,
struct omap_dss_device *dst)
{
WARN_ON(dst != dssdev->dst);
if (dst != dssdev->dst)
return;
omapdss_output_unset_device(dssdev);
if (dssdev->manager)
dss_mgr_disconnect(dssdev->manager, dssdev);
}
static int hdmi_read_edid(struct omap_dss_device *dssdev,
u8 *edid, int len)
{
bool need_enable;
int r;
need_enable = hdmi.core_enabled == false;
if (need_enable) {
r = hdmi_core_enable(dssdev);
if (r)
return r;
}
r = read_edid(edid, len);
if (need_enable)
hdmi_core_disable(dssdev);
return r;
}
#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
static int hdmi_audio_enable(struct omap_dss_device *dssdev)
{
int r;
mutex_lock(&hdmi.lock);
if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
r = -EPERM;
goto err;
}
r = hdmi_wp_audio_enable(&hdmi.wp, true);
if (r)
goto err;
mutex_unlock(&hdmi.lock);
return 0;
err:
mutex_unlock(&hdmi.lock);
return r;
}
static void hdmi_audio_disable(struct omap_dss_device *dssdev)
{
hdmi_wp_audio_enable(&hdmi.wp, false);
}
static int hdmi_audio_start(struct omap_dss_device *dssdev)
{
return hdmi_wp_audio_core_req_enable(&hdmi.wp, true);
}
static void hdmi_audio_stop(struct omap_dss_device *dssdev)
{
hdmi_wp_audio_core_req_enable(&hdmi.wp, false);
}
static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
{
bool r;
mutex_lock(&hdmi.lock);
r = hdmi_mode_has_audio(hdmi.cfg.cm.mode);
mutex_unlock(&hdmi.lock);
return r;
}
static int hdmi_audio_config(struct omap_dss_device *dssdev,
struct omap_dss_audio *audio)
{
int r;
u32 pclk = hdmi.cfg.timings.pixelclock;
mutex_lock(&hdmi.lock);
if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
r = -EPERM;
goto err;
}
r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
if (r)
goto err;
mutex_unlock(&hdmi.lock);
return 0;
err:
mutex_unlock(&hdmi.lock);
return r;
}
#else
static int hdmi_audio_enable(struct omap_dss_device *dssdev)
{
return -EPERM;
}
static void hdmi_audio_disable(struct omap_dss_device *dssdev)
{
}
static int hdmi_audio_start(struct omap_dss_device *dssdev)
{
return -EPERM;
}
static void hdmi_audio_stop(struct omap_dss_device *dssdev)
{
}
static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
{
return false;
}
static int hdmi_audio_config(struct omap_dss_device *dssdev,
struct omap_dss_audio *audio)
{
return -EPERM;
}
#endif
static const struct omapdss_hdmi_ops hdmi_ops = {
.connect = hdmi_connect,
.disconnect = hdmi_disconnect,
.enable = hdmi_display_enable,
.disable = hdmi_display_disable,
.check_timings = hdmi_display_check_timing,
.set_timings = hdmi_display_set_timing,
.get_timings = hdmi_display_get_timings,
.read_edid = hdmi_read_edid,
.audio_enable = hdmi_audio_enable,
.audio_disable = hdmi_audio_disable,
.audio_start = hdmi_audio_start,
.audio_stop = hdmi_audio_stop,
.audio_supported = hdmi_audio_supported,
.audio_config = hdmi_audio_config,
};
static void hdmi_init_output(struct platform_device *pdev)
{
struct omap_dss_device *out = &hdmi.output;
out->dev = &pdev->dev;
out->id = OMAP_DSS_OUTPUT_HDMI;
out->output_type = OMAP_DISPLAY_TYPE_HDMI;
out->name = "hdmi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
out->ops.hdmi = &hdmi_ops;
out->owner = THIS_MODULE;
omapdss_register_output(out);
}
static void __exit hdmi_uninit_output(struct platform_device *pdev)
{
struct omap_dss_device *out = &hdmi.output;
omapdss_unregister_output(out);
}
static int hdmi_probe_of(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct device_node *ep;
int r;
ep = omapdss_of_get_first_endpoint(node);
if (!ep)
return 0;
r = hdmi_parse_lanes_of(pdev, ep, &hdmi.phy);
if (r)
goto err;
of_node_put(ep);
return 0;
err:
of_node_put(ep);
return r;
}
/* HDMI HW IP initialisation */
static int omapdss_hdmihw_probe(struct platform_device *pdev)
{
int r;
int irq;
hdmi.pdev = pdev;
mutex_init(&hdmi.lock);
if (pdev->dev.of_node) {
r = hdmi_probe_of(pdev);
if (r)
return r;
}
r = hdmi_wp_init(pdev, &hdmi.wp);
if (r)
return r;
r = hdmi_pll_init(pdev, &hdmi.pll);
if (r)
return r;
r = hdmi_phy_init(pdev, &hdmi.phy);
if (r)
return r;
r = hdmi5_core_init(pdev, &hdmi.core);
if (r)
return r;
r = hdmi_get_clocks(pdev);
if (r) {
DSSERR("can't get clocks\n");
return r;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
DSSERR("platform_get_irq failed\n");
return -ENODEV;
}
r = devm_request_threaded_irq(&pdev->dev, irq,
NULL, hdmi_irq_handler,
IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
if (r) {
DSSERR("HDMI IRQ request failed\n");
return r;
}
pm_runtime_enable(&pdev->dev);
hdmi_init_output(pdev);
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
return 0;
}
static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
{
hdmi_uninit_output(pdev);
pm_runtime_disable(&pdev->dev);
return 0;
}
static int hdmi_runtime_suspend(struct device *dev)
{
clk_disable_unprepare(hdmi.sys_clk);
dispc_runtime_put();
return 0;
}
static int hdmi_runtime_resume(struct device *dev)
{
int r;
r = dispc_runtime_get();
if (r < 0)
return r;
clk_prepare_enable(hdmi.sys_clk);
return 0;
}
static const struct dev_pm_ops hdmi_pm_ops = {
.runtime_suspend = hdmi_runtime_suspend,
.runtime_resume = hdmi_runtime_resume,
};
static const struct of_device_id hdmi_of_match[] = {
{ .compatible = "ti,omap5-hdmi", },
{},
};
static struct platform_driver omapdss_hdmihw_driver = {
.probe = omapdss_hdmihw_probe,
.remove = __exit_p(omapdss_hdmihw_remove),
.driver = {
.name = "omapdss_hdmi5",
.owner = THIS_MODULE,
.pm = &hdmi_pm_ops,
.of_match_table = hdmi_of_match,
},
};
int __init hdmi5_init_platform_driver(void)
{
return platform_driver_register(&omapdss_hdmihw_driver);
}
void __exit hdmi5_uninit_platform_driver(void)
{
platform_driver_unregister(&omapdss_hdmihw_driver);
}
此差异已折叠。
/*
* HDMI driver definition for TI OMAP5 processors.
*
* Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _HDMI5_CORE_H_
#define _HDMI5_CORE_H_
#include "hdmi.h"
/* HDMI IP Core System */
/* HDMI Identification */
#define HDMI_CORE_DESIGN_ID 0x00000
#define HDMI_CORE_REVISION_ID 0x00004
#define HDMI_CORE_PRODUCT_ID0 0x00008
#define HDMI_CORE_PRODUCT_ID1 0x0000C
#define HDMI_CORE_CONFIG0_ID 0x00010
#define HDMI_CORE_CONFIG1_ID 0x00014
#define HDMI_CORE_CONFIG2_ID 0x00018
#define HDMI_CORE_CONFIG3_ID 0x0001C
/* HDMI Interrupt */
#define HDMI_CORE_IH_FC_STAT0 0x00400
#define HDMI_CORE_IH_FC_STAT1 0x00404
#define HDMI_CORE_IH_FC_STAT2 0x00408
#define HDMI_CORE_IH_AS_STAT0 0x0040C
#define HDMI_CORE_IH_PHY_STAT0 0x00410
#define HDMI_CORE_IH_I2CM_STAT0 0x00414
#define HDMI_CORE_IH_CEC_STAT0 0x00418
#define HDMI_CORE_IH_VP_STAT0 0x0041C
#define HDMI_CORE_IH_I2CMPHY_STAT0 0x00420
#define HDMI_CORE_IH_MUTE 0x007FC
/* HDMI Video Sampler */
#define HDMI_CORE_TX_INVID0 0x00800
#define HDMI_CORE_TX_INSTUFFING 0x00804
#define HDMI_CORE_TX_RGYDATA0 0x00808
#define HDMI_CORE_TX_RGYDATA1 0x0080C
#define HDMI_CORE_TX_RCRDATA0 0x00810
#define HDMI_CORE_TX_RCRDATA1 0x00814
#define HDMI_CORE_TX_BCBDATA0 0x00818
#define HDMI_CORE_TX_BCBDATA1 0x0081C
/* HDMI Video Packetizer */
#define HDMI_CORE_VP_STATUS 0x02000
#define HDMI_CORE_VP_PR_CD 0x02004
#define HDMI_CORE_VP_STUFF 0x02008
#define HDMI_CORE_VP_REMAP 0x0200C
#define HDMI_CORE_VP_CONF 0x02010
#define HDMI_CORE_VP_STAT 0x02014
#define HDMI_CORE_VP_INT 0x02018
#define HDMI_CORE_VP_MASK 0x0201C
#define HDMI_CORE_VP_POL 0x02020
/* Frame Composer */
#define HDMI_CORE_FC_INVIDCONF 0x04000
#define HDMI_CORE_FC_INHACTIV0 0x04004
#define HDMI_CORE_FC_INHACTIV1 0x04008
#define HDMI_CORE_FC_INHBLANK0 0x0400C
#define HDMI_CORE_FC_INHBLANK1 0x04010
#define HDMI_CORE_FC_INVACTIV0 0x04014
#define HDMI_CORE_FC_INVACTIV1 0x04018
#define HDMI_CORE_FC_INVBLANK 0x0401C
#define HDMI_CORE_FC_HSYNCINDELAY0 0x04020
#define HDMI_CORE_FC_HSYNCINDELAY1 0x04024
#define HDMI_CORE_FC_HSYNCINWIDTH0 0x04028
#define HDMI_CORE_FC_HSYNCINWIDTH1 0x0402C
#define HDMI_CORE_FC_VSYNCINDELAY 0x04030
#define HDMI_CORE_FC_VSYNCINWIDTH 0x04034
#define HDMI_CORE_FC_INFREQ0 0x04038
#define HDMI_CORE_FC_INFREQ1 0x0403C
#define HDMI_CORE_FC_INFREQ2 0x04040
#define HDMI_CORE_FC_CTRLDUR 0x04044
#define HDMI_CORE_FC_EXCTRLDUR 0x04048
#define HDMI_CORE_FC_EXCTRLSPAC 0x0404C
#define HDMI_CORE_FC_CH0PREAM 0x04050
#define HDMI_CORE_FC_CH1PREAM 0x04054
#define HDMI_CORE_FC_CH2PREAM 0x04058
#define HDMI_CORE_FC_AVICONF3 0x0405C
#define HDMI_CORE_FC_GCP 0x04060
#define HDMI_CORE_FC_AVICONF0 0x04064
#define HDMI_CORE_FC_AVICONF1 0x04068
#define HDMI_CORE_FC_AVICONF2 0x0406C
#define HDMI_CORE_FC_AVIVID 0x04070
#define HDMI_CORE_FC_AVIETB0 0x04074
#define HDMI_CORE_FC_AVIETB1 0x04078
#define HDMI_CORE_FC_AVISBB0 0x0407C
#define HDMI_CORE_FC_AVISBB1 0x04080
#define HDMI_CORE_FC_AVIELB0 0x04084
#define HDMI_CORE_FC_AVIELB1 0x04088
#define HDMI_CORE_FC_AVISRB0 0x0408C
#define HDMI_CORE_FC_AVISRB1 0x04090
#define HDMI_CORE_FC_AUDICONF0 0x04094
#define HDMI_CORE_FC_AUDICONF1 0x04098
#define HDMI_CORE_FC_AUDICONF2 0x0409C
#define HDMI_CORE_FC_AUDICONF3 0x040A0
#define HDMI_CORE_FC_VSDIEEEID0 0x040A4
#define HDMI_CORE_FC_VSDSIZE 0x040A8
#define HDMI_CORE_FC_VSDIEEEID1 0x040C0
#define HDMI_CORE_FC_VSDIEEEID2 0x040C4
#define HDMI_CORE_FC_VSDPAYLOAD(n) (n * 4 + 0x040C8)
#define HDMI_CORE_FC_SPDVENDORNAME(n) (n * 4 + 0x04128)
#define HDMI_CORE_FC_SPDPRODUCTNAME(n) (n * 4 + 0x04148)
#define HDMI_CORE_FC_SPDDEVICEINF 0x04188
#define HDMI_CORE_FC_AUDSCONF 0x0418C
#define HDMI_CORE_FC_AUDSSTAT 0x04190
#define HDMI_CORE_FC_AUDSV 0x04194
#define HDMI_CORE_FC_AUDSU 0x04198
#define HDMI_CORE_FC_AUDSCHNLS(n) (n * 4 + 0x0419C)
#define HDMI_CORE_FC_CTRLQHIGH 0x041CC
#define HDMI_CORE_FC_CTRLQLOW 0x041D0
#define HDMI_CORE_FC_ACP0 0x041D4
#define HDMI_CORE_FC_ACP(n) ((16-n) * 4 + 0x04208)
#define HDMI_CORE_FC_ISCR1_0 0x04248
#define HDMI_CORE_FC_ISCR1(n) ((16-n) * 4 + 0x0424C)
#define HDMI_CORE_FC_ISCR2(n) ((15-n) * 4 + 0x0428C)
#define HDMI_CORE_FC_DATAUTO0 0x042CC
#define HDMI_CORE_FC_DATAUTO1 0x042D0
#define HDMI_CORE_FC_DATAUTO2 0x042D4
#define HDMI_CORE_FC_DATMAN 0x042D8
#define HDMI_CORE_FC_DATAUTO3 0x042DC
#define HDMI_CORE_FC_RDRB(n) (n * 4 + 0x042E0)
#define HDMI_CORE_FC_STAT0 0x04340
#define HDMI_CORE_FC_INT0 0x04344
#define HDMI_CORE_FC_MASK0 0x04348
#define HDMI_CORE_FC_POL0 0x0434C
#define HDMI_CORE_FC_STAT1 0x04350
#define HDMI_CORE_FC_INT1 0x04354
#define HDMI_CORE_FC_MASK1 0x04358
#define HDMI_CORE_FC_POL1 0x0435C
#define HDMI_CORE_FC_STAT2 0x04360
#define HDMI_CORE_FC_INT2 0x04364
#define HDMI_CORE_FC_MASK2 0x04368
#define HDMI_CORE_FC_POL2 0x0436C
#define HDMI_CORE_FC_PRCONF 0x04380
#define HDMI_CORE_FC_GMD_STAT 0x04400
#define HDMI_CORE_FC_GMD_EN 0x04404
#define HDMI_CORE_FC_GMD_UP 0x04408
#define HDMI_CORE_FC_GMD_CONF 0x0440C
#define HDMI_CORE_FC_GMD_HB 0x04410
#define HDMI_CORE_FC_GMD_PB(n) (n * 4 + 0x04414)
#define HDMI_CORE_FC_DBGFORCE 0x04800
#define HDMI_CORE_FC_DBGAUD0CH0 0x04804
#define HDMI_CORE_FC_DBGAUD1CH0 0x04808
#define HDMI_CORE_FC_DBGAUD2CH0 0x0480C
#define HDMI_CORE_FC_DBGAUD0CH1 0x04810
#define HDMI_CORE_FC_DBGAUD1CH1 0x04814
#define HDMI_CORE_FC_DBGAUD2CH1 0x04818
#define HDMI_CORE_FC_DBGAUD0CH2 0x0481C
#define HDMI_CORE_FC_DBGAUD1CH2 0x04820
#define HDMI_CORE_FC_DBGAUD2CH2 0x04824
#define HDMI_CORE_FC_DBGAUD0CH3 0x04828
#define HDMI_CORE_FC_DBGAUD1CH3 0x0482C
#define HDMI_CORE_FC_DBGAUD2CH3 0x04830
#define HDMI_CORE_FC_DBGAUD0CH4 0x04834
#define HDMI_CORE_FC_DBGAUD1CH4 0x04838
#define HDMI_CORE_FC_DBGAUD2CH4 0x0483C
#define HDMI_CORE_FC_DBGAUD0CH5 0x04840
#define HDMI_CORE_FC_DBGAUD1CH5 0x04844
#define HDMI_CORE_FC_DBGAUD2CH5 0x04848
#define HDMI_CORE_FC_DBGAUD0CH6 0x0484C
#define HDMI_CORE_FC_DBGAUD1CH6 0x04850
#define HDMI_CORE_FC_DBGAUD2CH6 0x04854
#define HDMI_CORE_FC_DBGAUD0CH7 0x04858
#define HDMI_CORE_FC_DBGAUD1CH7 0x0485C
#define HDMI_CORE_FC_DBGAUD2CH7 0x04860
#define HDMI_CORE_FC_DBGTMDS0 0x04864
#define HDMI_CORE_FC_DBGTMDS1 0x04868
#define HDMI_CORE_FC_DBGTMDS2 0x0486C
#define HDMI_CORE_PHY_MASK0 0x0C018
#define HDMI_CORE_PHY_I2CM_INT_ADDR 0x0C09C
#define HDMI_CORE_PHY_I2CM_CTLINT_ADDR 0x0C0A0
/* HDMI Audio */
#define HDMI_CORE_AUD_CONF0 0x0C400
#define HDMI_CORE_AUD_CONF1 0x0C404
#define HDMI_CORE_AUD_INT 0x0C408
#define HDMI_CORE_AUD_N1 0x0C800
#define HDMI_CORE_AUD_N2 0x0C804
#define HDMI_CORE_AUD_N3 0x0C808
#define HDMI_CORE_AUD_CTS1 0x0C80C
#define HDMI_CORE_AUD_CTS2 0x0C810
#define HDMI_CORE_AUD_CTS3 0x0C814
#define HDMI_CORE_AUD_INCLKFS 0x0C818
#define HDMI_CORE_AUD_CC08 0x0CC08
#define HDMI_CORE_AUD_GP_CONF0 0x0D400
#define HDMI_CORE_AUD_GP_CONF1 0x0D404
#define HDMI_CORE_AUD_GP_CONF2 0x0D408
#define HDMI_CORE_AUD_D010 0x0D010
#define HDMI_CORE_AUD_GP_STAT 0x0D40C
#define HDMI_CORE_AUD_GP_INT 0x0D410
#define HDMI_CORE_AUD_GP_POL 0x0D414
#define HDMI_CORE_AUD_GP_MASK 0x0D418
/* HDMI Main Controller */
#define HDMI_CORE_MC_CLKDIS 0x10004
#define HDMI_CORE_MC_SWRSTZREQ 0x10008
#define HDMI_CORE_MC_FLOWCTRL 0x10010
#define HDMI_CORE_MC_PHYRSTZ 0x10014
#define HDMI_CORE_MC_LOCKONCLOCK 0x10018
/* HDMI COLOR SPACE CONVERTER */
#define HDMI_CORE_CSC_CFG 0x10400
#define HDMI_CORE_CSC_SCALE 0x10404
#define HDMI_CORE_CSC_COEF_A1_MSB 0x10408
#define HDMI_CORE_CSC_COEF_A1_LSB 0x1040C
#define HDMI_CORE_CSC_COEF_A2_MSB 0x10410
#define HDMI_CORE_CSC_COEF_A2_LSB 0x10414
#define HDMI_CORE_CSC_COEF_A3_MSB 0x10418
#define HDMI_CORE_CSC_COEF_A3_LSB 0x1041C
#define HDMI_CORE_CSC_COEF_A4_MSB 0x10420
#define HDMI_CORE_CSC_COEF_A4_LSB 0x10424
#define HDMI_CORE_CSC_COEF_B1_MSB 0x10428
#define HDMI_CORE_CSC_COEF_B1_LSB 0x1042C
#define HDMI_CORE_CSC_COEF_B2_MSB 0x10430
#define HDMI_CORE_CSC_COEF_B2_LSB 0x10434
#define HDMI_CORE_CSC_COEF_B3_MSB 0x10438
#define HDMI_CORE_CSC_COEF_B3_LSB 0x1043C
#define HDMI_CORE_CSC_COEF_B4_MSB 0x10440
#define HDMI_CORE_CSC_COEF_B4_LSB 0x10444
#define HDMI_CORE_CSC_COEF_C1_MSB 0x10448
#define HDMI_CORE_CSC_COEF_C1_LSB 0x1044C
#define HDMI_CORE_CSC_COEF_C2_MSB 0x10450
#define HDMI_CORE_CSC_COEF_C2_LSB 0x10454
#define HDMI_CORE_CSC_COEF_C3_MSB 0x10458
#define HDMI_CORE_CSC_COEF_C3_LSB 0x1045C
#define HDMI_CORE_CSC_COEF_C4_MSB 0x10460
#define HDMI_CORE_CSC_COEF_C4_LSB 0x10464
/* HDMI HDCP */
#define HDMI_CORE_HDCP_MASK 0x14020
/* HDMI CEC */
#define HDMI_CORE_CEC_MASK 0x17408
/* HDMI I2C Master */
#define HDMI_CORE_I2CM_SLAVE 0x157C8
#define HDMI_CORE_I2CM_ADDRESS 0x157CC
#define HDMI_CORE_I2CM_DATAO 0x157D0
#define HDMI_CORE_I2CM_DATAI 0X157D4
#define HDMI_CORE_I2CM_OPERATION 0x157D8
#define HDMI_CORE_I2CM_INT 0x157DC
#define HDMI_CORE_I2CM_CTLINT 0x157E0
#define HDMI_CORE_I2CM_DIV 0x157E4
#define HDMI_CORE_I2CM_SEGADDR 0x157E8
#define HDMI_CORE_I2CM_SOFTRSTZ 0x157EC
#define HDMI_CORE_I2CM_SEGPTR 0x157F0
#define HDMI_CORE_I2CM_SS_SCL_HCNT_1_ADDR 0x157F4
#define HDMI_CORE_I2CM_SS_SCL_HCNT_0_ADDR 0x157F8
#define HDMI_CORE_I2CM_SS_SCL_LCNT_1_ADDR 0x157FC
#define HDMI_CORE_I2CM_SS_SCL_LCNT_0_ADDR 0x15800
#define HDMI_CORE_I2CM_FS_SCL_HCNT_1_ADDR 0x15804
#define HDMI_CORE_I2CM_FS_SCL_HCNT_0_ADDR 0x15808
#define HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR 0x1580C
#define HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR 0x15810
#define HDMI_CORE_I2CM_SDA_HOLD_ADDR 0x15814
enum hdmi_core_packet_mode {
HDMI_PACKETMODERESERVEDVALUE = 0,
HDMI_PACKETMODE24BITPERPIXEL = 4,
HDMI_PACKETMODE30BITPERPIXEL = 5,
HDMI_PACKETMODE36BITPERPIXEL = 6,
HDMI_PACKETMODE48BITPERPIXEL = 7,
};
struct hdmi_core_vid_config {
struct hdmi_config v_fc_config;
enum hdmi_core_packet_mode packet_mode;
int data_enable_pol;
int vblank_osc;
int hblank;
int vblank;
};
struct csc_table {
u16 a1, a2, a3, a4;
u16 b1, b2, b3, b4;
u16 c1, c2, c3, c4;
};
int hdmi5_read_edid(struct hdmi_core_data *core, u8 *edid, int len);
void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s);
int hdmi5_core_handle_irqs(struct hdmi_core_data *core);
void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
struct hdmi_config *cfg);
int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
struct omap_dss_audio *audio, u32 pclk);
#endif
#endif
......@@ -185,7 +185,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
timings->interlace = param->timings.interlace;
}
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
struct hdmi_audio_format *aud_fmt)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册