Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,422 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "hdmi.h"
void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
{
uint32_t ctrl = 0;
if (power_on) {
ctrl |= HDMI_CTRL_ENABLE;
if (!hdmi->hdmi_mode) {
ctrl |= HDMI_CTRL_HDMI;
hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
ctrl &= ~HDMI_CTRL_HDMI;
} else {
ctrl |= HDMI_CTRL_HDMI;
}
} else {
ctrl = HDMI_CTRL_HDMI;
}
hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
DBG("HDMI Core: %s, HDMI_CTRL=0x%08x",
power_on ? "Enable" : "Disable", ctrl);
}
irqreturn_t hdmi_irq(int irq, void *dev_id)
{
struct hdmi *hdmi = dev_id;
/* Process HPD: */
hdmi_connector_irq(hdmi->connector);
/* Process DDC: */
hdmi_i2c_irq(hdmi->i2c);
/* TODO audio.. */
return IRQ_HANDLED;
}
void hdmi_destroy(struct kref *kref)
{
struct hdmi *hdmi = container_of(kref, struct hdmi, refcount);
struct hdmi_phy *phy = hdmi->phy;
if (phy)
phy->funcs->destroy(phy);
if (hdmi->i2c)
hdmi_i2c_destroy(hdmi->i2c);
platform_set_drvdata(hdmi->pdev, NULL);
}
/* initialize connector */
struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
{
struct hdmi *hdmi = NULL;
struct msm_drm_private *priv = dev->dev_private;
struct platform_device *pdev = priv->hdmi_pdev;
struct hdmi_platform_config *config;
int i, ret;
if (!pdev) {
dev_err(dev->dev, "no hdmi device\n");
ret = -ENXIO;
goto fail;
}
config = pdev->dev.platform_data;
hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
if (!hdmi) {
ret = -ENOMEM;
goto fail;
}
kref_init(&hdmi->refcount);
hdmi->dev = dev;
hdmi->pdev = pdev;
hdmi->config = config;
hdmi->encoder = encoder;
hdmi_audio_infoframe_init(&hdmi->audio.infoframe);
/* not sure about which phy maps to which msm.. probably I miss some */
if (config->phy_init)
hdmi->phy = config->phy_init(hdmi);
else
hdmi->phy = ERR_PTR(-ENXIO);
if (IS_ERR(hdmi->phy)) {
ret = PTR_ERR(hdmi->phy);
dev_err(dev->dev, "failed to load phy: %d\n", ret);
hdmi->phy = NULL;
goto fail;
}
hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI");
if (IS_ERR(hdmi->mmio)) {
ret = PTR_ERR(hdmi->mmio);
goto fail;
}
BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs));
for (i = 0; i < config->hpd_reg_cnt; i++) {
struct regulator *reg;
reg = devm_regulator_get(&pdev->dev,
config->hpd_reg_names[i]);
if (IS_ERR(reg)) {
ret = PTR_ERR(reg);
dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n",
config->hpd_reg_names[i], ret);
goto fail;
}
hdmi->hpd_regs[i] = reg;
}
BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs));
for (i = 0; i < config->pwr_reg_cnt; i++) {
struct regulator *reg;
reg = devm_regulator_get(&pdev->dev,
config->pwr_reg_names[i]);
if (IS_ERR(reg)) {
ret = PTR_ERR(reg);
dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n",
config->pwr_reg_names[i], ret);
goto fail;
}
hdmi->pwr_regs[i] = reg;
}
BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks));
for (i = 0; i < config->hpd_clk_cnt; i++) {
struct clk *clk;
clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
dev_err(dev->dev, "failed to get hpd clk: %s (%d)\n",
config->hpd_clk_names[i], ret);
goto fail;
}
hdmi->hpd_clks[i] = clk;
}
BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks));
for (i = 0; i < config->pwr_clk_cnt; i++) {
struct clk *clk;
clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
dev_err(dev->dev, "failed to get pwr clk: %s (%d)\n",
config->pwr_clk_names[i], ret);
goto fail;
}
hdmi->pwr_clks[i] = clk;
}
hdmi->i2c = hdmi_i2c_init(hdmi);
if (IS_ERR(hdmi->i2c)) {
ret = PTR_ERR(hdmi->i2c);
dev_err(dev->dev, "failed to get i2c: %d\n", ret);
hdmi->i2c = NULL;
goto fail;
}
hdmi->bridge = hdmi_bridge_init(hdmi);
if (IS_ERR(hdmi->bridge)) {
ret = PTR_ERR(hdmi->bridge);
dev_err(dev->dev, "failed to create HDMI bridge: %d\n", ret);
hdmi->bridge = NULL;
goto fail;
}
hdmi->connector = hdmi_connector_init(hdmi);
if (IS_ERR(hdmi->connector)) {
ret = PTR_ERR(hdmi->connector);
dev_err(dev->dev, "failed to create HDMI connector: %d\n", ret);
hdmi->connector = NULL;
goto fail;
}
if (!config->shared_irq) {
hdmi->irq = platform_get_irq(pdev, 0);
if (hdmi->irq < 0) {
ret = hdmi->irq;
dev_err(dev->dev, "failed to get irq: %d\n", ret);
goto fail;
}
ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"hdmi_isr", hdmi);
if (ret < 0) {
dev_err(dev->dev, "failed to request IRQ%u: %d\n",
hdmi->irq, ret);
goto fail;
}
}
encoder->bridge = hdmi->bridge;
priv->bridges[priv->num_bridges++] = hdmi->bridge;
priv->connectors[priv->num_connectors++] = hdmi->connector;
platform_set_drvdata(pdev, hdmi);
return hdmi;
fail:
if (hdmi) {
/* bridge/connector are normally destroyed by drm: */
if (hdmi->bridge)
hdmi->bridge->funcs->destroy(hdmi->bridge);
if (hdmi->connector)
hdmi->connector->funcs->destroy(hdmi->connector);
hdmi_destroy(&hdmi->refcount);
}
return ERR_PTR(ret);
}
/*
* The hdmi device:
*/
#include <linux/of_gpio.h>
static void set_hdmi_pdev(struct drm_device *dev,
struct platform_device *pdev)
{
struct msm_drm_private *priv = dev->dev_private;
priv->hdmi_pdev = pdev;
}
#ifdef CONFIG_OF
static int get_gpio(struct device *dev, struct device_node *of_node, const char *name)
{
int gpio = of_get_named_gpio(of_node, name, 0);
if (gpio < 0) {
char name2[32];
snprintf(name2, sizeof(name2), "%s-gpio", name);
gpio = of_get_named_gpio(of_node, name2, 0);
if (gpio < 0) {
dev_err(dev, "failed to get gpio: %s (%d)\n",
name, gpio);
gpio = -1;
}
}
return gpio;
}
#endif
static int hdmi_bind(struct device *dev, struct device *master, void *data)
{
static struct hdmi_platform_config config = {};
#ifdef CONFIG_OF
struct device_node *of_node = dev->of_node;
if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8074")) {
static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
static unsigned long hpd_clk_freq[] = {0, 19200000, 0};
static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
config.phy_init = hdmi_phy_8x74_init;
config.hpd_reg_names = hpd_reg_names;
config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
config.pwr_reg_names = pwr_reg_names;
config.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names);
config.hpd_clk_names = hpd_clk_names;
config.hpd_freq = hpd_clk_freq;
config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
config.pwr_clk_names = pwr_clk_names;
config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names);
config.shared_irq = true;
} else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8960")) {
static const char *hpd_clk_names[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
static const char *hpd_reg_names[] = {"core-vdda", "hdmi-mux"};
config.phy_init = hdmi_phy_8960_init;
config.hpd_reg_names = hpd_reg_names;
config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
config.hpd_clk_names = hpd_clk_names;
config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
} else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8660")) {
config.phy_init = hdmi_phy_8x60_init;
} else {
dev_err(dev, "unknown phy: %s\n", of_node->name);
}
config.mmio_name = "core_physical";
config.ddc_clk_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-clk");
config.ddc_data_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-data");
config.hpd_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-hpd");
config.mux_en_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-en");
config.mux_sel_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-sel");
config.mux_lpm_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-lpm");
#else
static const char *hpd_clk_names[] = {
"core_clk", "master_iface_clk", "slave_iface_clk",
};
if (cpu_is_apq8064()) {
static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
config.phy_init = hdmi_phy_8960_init;
config.mmio_name = "hdmi_msm_hdmi_addr";
config.hpd_reg_names = hpd_reg_names;
config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
config.hpd_clk_names = hpd_clk_names;
config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
config.ddc_clk_gpio = 70;
config.ddc_data_gpio = 71;
config.hpd_gpio = 72;
config.mux_en_gpio = -1;
config.mux_sel_gpio = -1;
} else if (cpu_is_msm8960() || cpu_is_msm8960ab()) {
static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
config.phy_init = hdmi_phy_8960_init;
config.mmio_name = "hdmi_msm_hdmi_addr";
config.hpd_reg_names = hpd_reg_names;
config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
config.hpd_clk_names = hpd_clk_names;
config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
config.ddc_clk_gpio = 100;
config.ddc_data_gpio = 101;
config.hpd_gpio = 102;
config.mux_en_gpio = -1;
config.mux_sel_gpio = -1;
} else if (cpu_is_msm8x60()) {
static const char *hpd_reg_names[] = {
"8901_hdmi_mvs", "8901_mpp0"
};
config.phy_init = hdmi_phy_8x60_init;
config.mmio_name = "hdmi_msm_hdmi_addr";
config.hpd_reg_names = hpd_reg_names;
config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
config.hpd_clk_names = hpd_clk_names;
config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
config.ddc_clk_gpio = 170;
config.ddc_data_gpio = 171;
config.hpd_gpio = 172;
config.mux_en_gpio = -1;
config.mux_sel_gpio = -1;
}
#endif
dev->platform_data = &config;
set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev));
return 0;
}
static void hdmi_unbind(struct device *dev, struct device *master,
void *data)
{
set_hdmi_pdev(dev_get_drvdata(master), NULL);
}
static const struct component_ops hdmi_ops = {
.bind = hdmi_bind,
.unbind = hdmi_unbind,
};
static int hdmi_dev_probe(struct platform_device *pdev)
{
return component_add(&pdev->dev, &hdmi_ops);
}
static int hdmi_dev_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &hdmi_ops);
return 0;
}
static const struct of_device_id dt_match[] = {
{ .compatible = "qcom,hdmi-tx-8074" },
{ .compatible = "qcom,hdmi-tx-8960" },
{ .compatible = "qcom,hdmi-tx-8660" },
{}
};
static struct platform_driver hdmi_driver = {
.probe = hdmi_dev_probe,
.remove = hdmi_dev_remove,
.driver = {
.name = "hdmi_msm",
.of_match_table = dt_match,
},
};
void __init hdmi_register(void)
{
platform_driver_register(&hdmi_driver);
}
void __exit hdmi_unregister(void)
{
platform_driver_unregister(&hdmi_driver);
}

View file

@ -0,0 +1,182 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __HDMI_CONNECTOR_H__
#define __HDMI_CONNECTOR_H__
#include <linux/i2c.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/hdmi.h>
#include "msm_drv.h"
#include "hdmi.xml.h"
struct hdmi_phy;
struct hdmi_platform_config;
struct hdmi_audio {
bool enabled;
struct hdmi_audio_infoframe infoframe;
int rate;
};
struct hdmi {
struct kref refcount;
struct drm_device *dev;
struct platform_device *pdev;
const struct hdmi_platform_config *config;
/* audio state: */
struct hdmi_audio audio;
/* video state: */
bool power_on;
unsigned long int pixclock;
void __iomem *mmio;
struct regulator *hpd_regs[2];
struct regulator *pwr_regs[2];
struct clk *hpd_clks[3];
struct clk *pwr_clks[2];
struct hdmi_phy *phy;
struct i2c_adapter *i2c;
struct drm_connector *connector;
struct drm_bridge *bridge;
/* the encoder we are hooked to (outside of hdmi block) */
struct drm_encoder *encoder;
bool hdmi_mode; /* are we in hdmi mode? */
int irq;
};
/* platform config data (ie. from DT, or pdata) */
struct hdmi_platform_config {
struct hdmi_phy *(*phy_init)(struct hdmi *hdmi);
const char *mmio_name;
/* regulators that need to be on for hpd: */
const char **hpd_reg_names;
int hpd_reg_cnt;
/* regulators that need to be on for screen pwr: */
const char **pwr_reg_names;
int pwr_reg_cnt;
/* clks that need to be on for hpd: */
const char **hpd_clk_names;
const long unsigned *hpd_freq;
int hpd_clk_cnt;
/* clks that need to be on for screen pwr (ie pixel clk): */
const char **pwr_clk_names;
int pwr_clk_cnt;
/* gpio's: */
int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, mux_en_gpio, mux_sel_gpio;
int mux_lpm_gpio;
/* older devices had their own irq, mdp5+ it is shared w/ mdp: */
bool shared_irq;
};
void hdmi_set_mode(struct hdmi *hdmi, bool power_on);
void hdmi_destroy(struct kref *kref);
static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
{
msm_writel(data, hdmi->mmio + reg);
}
static inline u32 hdmi_read(struct hdmi *hdmi, u32 reg)
{
return msm_readl(hdmi->mmio + reg);
}
static inline struct hdmi * hdmi_reference(struct hdmi *hdmi)
{
kref_get(&hdmi->refcount);
return hdmi;
}
static inline void hdmi_unreference(struct hdmi *hdmi)
{
kref_put(&hdmi->refcount, hdmi_destroy);
}
/*
* The phy appears to be different, for example between 8960 and 8x60,
* so split the phy related functions out and load the correct one at
* runtime:
*/
struct hdmi_phy_funcs {
void (*destroy)(struct hdmi_phy *phy);
void (*reset)(struct hdmi_phy *phy);
void (*powerup)(struct hdmi_phy *phy, unsigned long int pixclock);
void (*powerdown)(struct hdmi_phy *phy);
};
struct hdmi_phy {
const struct hdmi_phy_funcs *funcs;
};
struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi);
struct hdmi_phy *hdmi_phy_8x60_init(struct hdmi *hdmi);
struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi);
/*
* audio:
*/
int hdmi_audio_update(struct hdmi *hdmi);
int hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,
uint32_t num_of_channels, uint32_t channel_allocation,
uint32_t level_shift, bool down_mix);
void hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate);
/*
* hdmi bridge:
*/
struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi);
/*
* hdmi connector:
*/
void hdmi_connector_irq(struct drm_connector *connector);
struct drm_connector *hdmi_connector_init(struct hdmi *hdmi);
/*
* i2c adapter for ddc:
*/
void hdmi_i2c_irq(struct i2c_adapter *i2c);
void hdmi_i2c_destroy(struct i2c_adapter *i2c);
struct i2c_adapter *hdmi_i2c_init(struct hdmi *hdmi);
#endif /* __HDMI_CONNECTOR_H__ */

View file

@ -0,0 +1,672 @@
#ifndef HDMI_XML
#define HDMI_XML
/* Autogenerated file, DO NOT EDIT manually!
This file was generated by the rules-ng-ng headergen tool in this git repository:
http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20457 bytes, from 2014-08-01 12:22:48)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-07-17 15:34:33)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30)
Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
enum hdmi_hdcp_key_state {
NO_KEYS = 0,
NOT_CHECKED = 1,
CHECKING = 2,
KEYS_VALID = 3,
AKSV_INVALID = 4,
CHECKSUM_MISMATCH = 5,
};
enum hdmi_ddc_read_write {
DDC_WRITE = 0,
DDC_READ = 1,
};
enum hdmi_acr_cts {
ACR_NONE = 0,
ACR_32 = 1,
ACR_44 = 2,
ACR_48 = 3,
};
#define REG_HDMI_CTRL 0x00000000
#define HDMI_CTRL_ENABLE 0x00000001
#define HDMI_CTRL_HDMI 0x00000002
#define HDMI_CTRL_ENCRYPTED 0x00000004
#define REG_HDMI_AUDIO_PKT_CTRL1 0x00000020
#define HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND 0x00000001
#define REG_HDMI_ACR_PKT_CTRL 0x00000024
#define HDMI_ACR_PKT_CTRL_CONT 0x00000001
#define HDMI_ACR_PKT_CTRL_SEND 0x00000002
#define HDMI_ACR_PKT_CTRL_SELECT__MASK 0x00000030
#define HDMI_ACR_PKT_CTRL_SELECT__SHIFT 4
static inline uint32_t HDMI_ACR_PKT_CTRL_SELECT(enum hdmi_acr_cts val)
{
return ((val) << HDMI_ACR_PKT_CTRL_SELECT__SHIFT) & HDMI_ACR_PKT_CTRL_SELECT__MASK;
}
#define HDMI_ACR_PKT_CTRL_SOURCE 0x00000100
#define HDMI_ACR_PKT_CTRL_N_MULTIPLIER__MASK 0x00070000
#define HDMI_ACR_PKT_CTRL_N_MULTIPLIER__SHIFT 16
static inline uint32_t HDMI_ACR_PKT_CTRL_N_MULTIPLIER(uint32_t val)
{
return ((val) << HDMI_ACR_PKT_CTRL_N_MULTIPLIER__SHIFT) & HDMI_ACR_PKT_CTRL_N_MULTIPLIER__MASK;
}
#define HDMI_ACR_PKT_CTRL_AUDIO_PRIORITY 0x80000000
#define REG_HDMI_VBI_PKT_CTRL 0x00000028
#define HDMI_VBI_PKT_CTRL_GC_ENABLE 0x00000010
#define HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME 0x00000020
#define HDMI_VBI_PKT_CTRL_ISRC_SEND 0x00000100
#define HDMI_VBI_PKT_CTRL_ISRC_CONTINUOUS 0x00000200
#define HDMI_VBI_PKT_CTRL_ACP_SEND 0x00001000
#define HDMI_VBI_PKT_CTRL_ACP_SRC_SW 0x00002000
#define REG_HDMI_INFOFRAME_CTRL0 0x0000002c
#define HDMI_INFOFRAME_CTRL0_AVI_SEND 0x00000001
#define HDMI_INFOFRAME_CTRL0_AVI_CONT 0x00000002
#define HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND 0x00000010
#define HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT 0x00000020
#define HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE 0x00000040
#define HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE 0x00000080
#define REG_HDMI_GEN_PKT_CTRL 0x00000034
#define HDMI_GEN_PKT_CTRL_GENERIC0_SEND 0x00000001
#define HDMI_GEN_PKT_CTRL_GENERIC0_CONT 0x00000002
#define HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE__MASK 0x0000000c
#define HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE__SHIFT 2
static inline uint32_t HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE(uint32_t val)
{
return ((val) << HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE__SHIFT) & HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE__MASK;
}
#define HDMI_GEN_PKT_CTRL_GENERIC1_SEND 0x00000010
#define HDMI_GEN_PKT_CTRL_GENERIC1_CONT 0x00000020
#define HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK 0x003f0000
#define HDMI_GEN_PKT_CTRL_GENERIC0_LINE__SHIFT 16
static inline uint32_t HDMI_GEN_PKT_CTRL_GENERIC0_LINE(uint32_t val)
{
return ((val) << HDMI_GEN_PKT_CTRL_GENERIC0_LINE__SHIFT) & HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK;
}
#define HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK 0x3f000000
#define HDMI_GEN_PKT_CTRL_GENERIC1_LINE__SHIFT 24
static inline uint32_t HDMI_GEN_PKT_CTRL_GENERIC1_LINE(uint32_t val)
{
return ((val) << HDMI_GEN_PKT_CTRL_GENERIC1_LINE__SHIFT) & HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK;
}
#define REG_HDMI_GC 0x00000040
#define HDMI_GC_MUTE 0x00000001
#define REG_HDMI_AUDIO_PKT_CTRL2 0x00000044
#define HDMI_AUDIO_PKT_CTRL2_OVERRIDE 0x00000001
#define HDMI_AUDIO_PKT_CTRL2_LAYOUT 0x00000002
static inline uint32_t REG_HDMI_AVI_INFO(uint32_t i0) { return 0x0000006c + 0x4*i0; }
#define REG_HDMI_GENERIC0_HDR 0x00000084
static inline uint32_t REG_HDMI_GENERIC0(uint32_t i0) { return 0x00000088 + 0x4*i0; }
#define REG_HDMI_GENERIC1_HDR 0x000000a4
static inline uint32_t REG_HDMI_GENERIC1(uint32_t i0) { return 0x000000a8 + 0x4*i0; }
static inline uint32_t REG_HDMI_ACR(enum hdmi_acr_cts i0) { return 0x000000c4 + 0x8*i0; }
static inline uint32_t REG_HDMI_ACR_0(enum hdmi_acr_cts i0) { return 0x000000c4 + 0x8*i0; }
#define HDMI_ACR_0_CTS__MASK 0xfffff000
#define HDMI_ACR_0_CTS__SHIFT 12
static inline uint32_t HDMI_ACR_0_CTS(uint32_t val)
{
return ((val) << HDMI_ACR_0_CTS__SHIFT) & HDMI_ACR_0_CTS__MASK;
}
static inline uint32_t REG_HDMI_ACR_1(enum hdmi_acr_cts i0) { return 0x000000c8 + 0x8*i0; }
#define HDMI_ACR_1_N__MASK 0xffffffff
#define HDMI_ACR_1_N__SHIFT 0
static inline uint32_t HDMI_ACR_1_N(uint32_t val)
{
return ((val) << HDMI_ACR_1_N__SHIFT) & HDMI_ACR_1_N__MASK;
}
#define REG_HDMI_AUDIO_INFO0 0x000000e4
#define HDMI_AUDIO_INFO0_CHECKSUM__MASK 0x000000ff
#define HDMI_AUDIO_INFO0_CHECKSUM__SHIFT 0
static inline uint32_t HDMI_AUDIO_INFO0_CHECKSUM(uint32_t val)
{
return ((val) << HDMI_AUDIO_INFO0_CHECKSUM__SHIFT) & HDMI_AUDIO_INFO0_CHECKSUM__MASK;
}
#define HDMI_AUDIO_INFO0_CC__MASK 0x00000700
#define HDMI_AUDIO_INFO0_CC__SHIFT 8
static inline uint32_t HDMI_AUDIO_INFO0_CC(uint32_t val)
{
return ((val) << HDMI_AUDIO_INFO0_CC__SHIFT) & HDMI_AUDIO_INFO0_CC__MASK;
}
#define REG_HDMI_AUDIO_INFO1 0x000000e8
#define HDMI_AUDIO_INFO1_CA__MASK 0x000000ff
#define HDMI_AUDIO_INFO1_CA__SHIFT 0
static inline uint32_t HDMI_AUDIO_INFO1_CA(uint32_t val)
{
return ((val) << HDMI_AUDIO_INFO1_CA__SHIFT) & HDMI_AUDIO_INFO1_CA__MASK;
}
#define HDMI_AUDIO_INFO1_LSV__MASK 0x00007800
#define HDMI_AUDIO_INFO1_LSV__SHIFT 11
static inline uint32_t HDMI_AUDIO_INFO1_LSV(uint32_t val)
{
return ((val) << HDMI_AUDIO_INFO1_LSV__SHIFT) & HDMI_AUDIO_INFO1_LSV__MASK;
}
#define HDMI_AUDIO_INFO1_DM_INH 0x00008000
#define REG_HDMI_HDCP_CTRL 0x00000110
#define HDMI_HDCP_CTRL_ENABLE 0x00000001
#define HDMI_HDCP_CTRL_ENCRYPTION_ENABLE 0x00000100
#define REG_HDMI_HDCP_INT_CTRL 0x00000118
#define REG_HDMI_HDCP_LINK0_STATUS 0x0000011c
#define HDMI_HDCP_LINK0_STATUS_AN_0_READY 0x00000100
#define HDMI_HDCP_LINK0_STATUS_AN_1_READY 0x00000200
#define HDMI_HDCP_LINK0_STATUS_KEY_STATE__MASK 0x70000000
#define HDMI_HDCP_LINK0_STATUS_KEY_STATE__SHIFT 28
static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state val)
{
return ((val) << HDMI_HDCP_LINK0_STATUS_KEY_STATE__SHIFT) & HDMI_HDCP_LINK0_STATUS_KEY_STATE__MASK;
}
#define REG_HDMI_HDCP_RESET 0x00000130
#define HDMI_HDCP_RESET_LINK0_DEAUTHENTICATE 0x00000001
#define REG_HDMI_VENSPEC_INFO0 0x0000016c
#define REG_HDMI_VENSPEC_INFO1 0x00000170
#define REG_HDMI_VENSPEC_INFO2 0x00000174
#define REG_HDMI_VENSPEC_INFO3 0x00000178
#define REG_HDMI_VENSPEC_INFO4 0x0000017c
#define REG_HDMI_VENSPEC_INFO5 0x00000180
#define REG_HDMI_VENSPEC_INFO6 0x00000184
#define REG_HDMI_AUDIO_CFG 0x000001d0
#define HDMI_AUDIO_CFG_ENGINE_ENABLE 0x00000001
#define HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK 0x000000f0
#define HDMI_AUDIO_CFG_FIFO_WATERMARK__SHIFT 4
static inline uint32_t HDMI_AUDIO_CFG_FIFO_WATERMARK(uint32_t val)
{
return ((val) << HDMI_AUDIO_CFG_FIFO_WATERMARK__SHIFT) & HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK;
}
#define REG_HDMI_USEC_REFTIMER 0x00000208
#define REG_HDMI_DDC_CTRL 0x0000020c
#define HDMI_DDC_CTRL_GO 0x00000001
#define HDMI_DDC_CTRL_SOFT_RESET 0x00000002
#define HDMI_DDC_CTRL_SEND_RESET 0x00000004
#define HDMI_DDC_CTRL_SW_STATUS_RESET 0x00000008
#define HDMI_DDC_CTRL_TRANSACTION_CNT__MASK 0x00300000
#define HDMI_DDC_CTRL_TRANSACTION_CNT__SHIFT 20
static inline uint32_t HDMI_DDC_CTRL_TRANSACTION_CNT(uint32_t val)
{
return ((val) << HDMI_DDC_CTRL_TRANSACTION_CNT__SHIFT) & HDMI_DDC_CTRL_TRANSACTION_CNT__MASK;
}
#define REG_HDMI_DDC_ARBITRATION 0x00000210
#define HDMI_DDC_ARBITRATION_HW_ARBITRATION 0x00000010
#define REG_HDMI_DDC_INT_CTRL 0x00000214
#define HDMI_DDC_INT_CTRL_SW_DONE_INT 0x00000001
#define HDMI_DDC_INT_CTRL_SW_DONE_ACK 0x00000002
#define HDMI_DDC_INT_CTRL_SW_DONE_MASK 0x00000004
#define REG_HDMI_DDC_SW_STATUS 0x00000218
#define HDMI_DDC_SW_STATUS_NACK0 0x00001000
#define HDMI_DDC_SW_STATUS_NACK1 0x00002000
#define HDMI_DDC_SW_STATUS_NACK2 0x00004000
#define HDMI_DDC_SW_STATUS_NACK3 0x00008000
#define REG_HDMI_DDC_HW_STATUS 0x0000021c
#define REG_HDMI_DDC_SPEED 0x00000220
#define HDMI_DDC_SPEED_THRESHOLD__MASK 0x00000003
#define HDMI_DDC_SPEED_THRESHOLD__SHIFT 0
static inline uint32_t HDMI_DDC_SPEED_THRESHOLD(uint32_t val)
{
return ((val) << HDMI_DDC_SPEED_THRESHOLD__SHIFT) & HDMI_DDC_SPEED_THRESHOLD__MASK;
}
#define HDMI_DDC_SPEED_PRESCALE__MASK 0xffff0000
#define HDMI_DDC_SPEED_PRESCALE__SHIFT 16
static inline uint32_t HDMI_DDC_SPEED_PRESCALE(uint32_t val)
{
return ((val) << HDMI_DDC_SPEED_PRESCALE__SHIFT) & HDMI_DDC_SPEED_PRESCALE__MASK;
}
#define REG_HDMI_DDC_SETUP 0x00000224
#define HDMI_DDC_SETUP_TIMEOUT__MASK 0xff000000
#define HDMI_DDC_SETUP_TIMEOUT__SHIFT 24
static inline uint32_t HDMI_DDC_SETUP_TIMEOUT(uint32_t val)
{
return ((val) << HDMI_DDC_SETUP_TIMEOUT__SHIFT) & HDMI_DDC_SETUP_TIMEOUT__MASK;
}
static inline uint32_t REG_HDMI_I2C_TRANSACTION(uint32_t i0) { return 0x00000228 + 0x4*i0; }
static inline uint32_t REG_HDMI_I2C_TRANSACTION_REG(uint32_t i0) { return 0x00000228 + 0x4*i0; }
#define HDMI_I2C_TRANSACTION_REG_RW__MASK 0x00000001
#define HDMI_I2C_TRANSACTION_REG_RW__SHIFT 0
static inline uint32_t HDMI_I2C_TRANSACTION_REG_RW(enum hdmi_ddc_read_write val)
{
return ((val) << HDMI_I2C_TRANSACTION_REG_RW__SHIFT) & HDMI_I2C_TRANSACTION_REG_RW__MASK;
}
#define HDMI_I2C_TRANSACTION_REG_STOP_ON_NACK 0x00000100
#define HDMI_I2C_TRANSACTION_REG_START 0x00001000
#define HDMI_I2C_TRANSACTION_REG_STOP 0x00002000
#define HDMI_I2C_TRANSACTION_REG_CNT__MASK 0x00ff0000
#define HDMI_I2C_TRANSACTION_REG_CNT__SHIFT 16
static inline uint32_t HDMI_I2C_TRANSACTION_REG_CNT(uint32_t val)
{
return ((val) << HDMI_I2C_TRANSACTION_REG_CNT__SHIFT) & HDMI_I2C_TRANSACTION_REG_CNT__MASK;
}
#define REG_HDMI_DDC_DATA 0x00000238
#define HDMI_DDC_DATA_DATA_RW__MASK 0x00000001
#define HDMI_DDC_DATA_DATA_RW__SHIFT 0
static inline uint32_t HDMI_DDC_DATA_DATA_RW(enum hdmi_ddc_read_write val)
{
return ((val) << HDMI_DDC_DATA_DATA_RW__SHIFT) & HDMI_DDC_DATA_DATA_RW__MASK;
}
#define HDMI_DDC_DATA_DATA__MASK 0x0000ff00
#define HDMI_DDC_DATA_DATA__SHIFT 8
static inline uint32_t HDMI_DDC_DATA_DATA(uint32_t val)
{
return ((val) << HDMI_DDC_DATA_DATA__SHIFT) & HDMI_DDC_DATA_DATA__MASK;
}
#define HDMI_DDC_DATA_INDEX__MASK 0x00ff0000
#define HDMI_DDC_DATA_INDEX__SHIFT 16
static inline uint32_t HDMI_DDC_DATA_INDEX(uint32_t val)
{
return ((val) << HDMI_DDC_DATA_INDEX__SHIFT) & HDMI_DDC_DATA_INDEX__MASK;
}
#define HDMI_DDC_DATA_INDEX_WRITE 0x80000000
#define REG_HDMI_HPD_INT_STATUS 0x00000250
#define HDMI_HPD_INT_STATUS_INT 0x00000001
#define HDMI_HPD_INT_STATUS_CABLE_DETECTED 0x00000002
#define REG_HDMI_HPD_INT_CTRL 0x00000254
#define HDMI_HPD_INT_CTRL_INT_ACK 0x00000001
#define HDMI_HPD_INT_CTRL_INT_CONNECT 0x00000002
#define HDMI_HPD_INT_CTRL_INT_EN 0x00000004
#define HDMI_HPD_INT_CTRL_RX_INT_ACK 0x00000010
#define HDMI_HPD_INT_CTRL_RX_INT_EN 0x00000020
#define HDMI_HPD_INT_CTRL_RCV_PLUGIN_DET_MASK 0x00000200
#define REG_HDMI_HPD_CTRL 0x00000258
#define HDMI_HPD_CTRL_TIMEOUT__MASK 0x00001fff
#define HDMI_HPD_CTRL_TIMEOUT__SHIFT 0
static inline uint32_t HDMI_HPD_CTRL_TIMEOUT(uint32_t val)
{
return ((val) << HDMI_HPD_CTRL_TIMEOUT__SHIFT) & HDMI_HPD_CTRL_TIMEOUT__MASK;
}
#define HDMI_HPD_CTRL_ENABLE 0x10000000
#define REG_HDMI_DDC_REF 0x0000027c
#define HDMI_DDC_REF_REFTIMER_ENABLE 0x00010000
#define HDMI_DDC_REF_REFTIMER__MASK 0x0000ffff
#define HDMI_DDC_REF_REFTIMER__SHIFT 0
static inline uint32_t HDMI_DDC_REF_REFTIMER(uint32_t val)
{
return ((val) << HDMI_DDC_REF_REFTIMER__SHIFT) & HDMI_DDC_REF_REFTIMER__MASK;
}
#define REG_HDMI_CEC_STATUS 0x00000298
#define REG_HDMI_CEC_INT 0x0000029c
#define REG_HDMI_CEC_ADDR 0x000002a0
#define REG_HDMI_CEC_TIME 0x000002a4
#define REG_HDMI_CEC_REFTIMER 0x000002a8
#define REG_HDMI_CEC_RD_DATA 0x000002ac
#define REG_HDMI_CEC_RD_FILTER 0x000002b0
#define REG_HDMI_ACTIVE_HSYNC 0x000002b4
#define HDMI_ACTIVE_HSYNC_START__MASK 0x00000fff
#define HDMI_ACTIVE_HSYNC_START__SHIFT 0
static inline uint32_t HDMI_ACTIVE_HSYNC_START(uint32_t val)
{
return ((val) << HDMI_ACTIVE_HSYNC_START__SHIFT) & HDMI_ACTIVE_HSYNC_START__MASK;
}
#define HDMI_ACTIVE_HSYNC_END__MASK 0x0fff0000
#define HDMI_ACTIVE_HSYNC_END__SHIFT 16
static inline uint32_t HDMI_ACTIVE_HSYNC_END(uint32_t val)
{
return ((val) << HDMI_ACTIVE_HSYNC_END__SHIFT) & HDMI_ACTIVE_HSYNC_END__MASK;
}
#define REG_HDMI_ACTIVE_VSYNC 0x000002b8
#define HDMI_ACTIVE_VSYNC_START__MASK 0x00000fff
#define HDMI_ACTIVE_VSYNC_START__SHIFT 0
static inline uint32_t HDMI_ACTIVE_VSYNC_START(uint32_t val)
{
return ((val) << HDMI_ACTIVE_VSYNC_START__SHIFT) & HDMI_ACTIVE_VSYNC_START__MASK;
}
#define HDMI_ACTIVE_VSYNC_END__MASK 0x0fff0000
#define HDMI_ACTIVE_VSYNC_END__SHIFT 16
static inline uint32_t HDMI_ACTIVE_VSYNC_END(uint32_t val)
{
return ((val) << HDMI_ACTIVE_VSYNC_END__SHIFT) & HDMI_ACTIVE_VSYNC_END__MASK;
}
#define REG_HDMI_VSYNC_ACTIVE_F2 0x000002bc
#define HDMI_VSYNC_ACTIVE_F2_START__MASK 0x00000fff
#define HDMI_VSYNC_ACTIVE_F2_START__SHIFT 0
static inline uint32_t HDMI_VSYNC_ACTIVE_F2_START(uint32_t val)
{
return ((val) << HDMI_VSYNC_ACTIVE_F2_START__SHIFT) & HDMI_VSYNC_ACTIVE_F2_START__MASK;
}
#define HDMI_VSYNC_ACTIVE_F2_END__MASK 0x0fff0000
#define HDMI_VSYNC_ACTIVE_F2_END__SHIFT 16
static inline uint32_t HDMI_VSYNC_ACTIVE_F2_END(uint32_t val)
{
return ((val) << HDMI_VSYNC_ACTIVE_F2_END__SHIFT) & HDMI_VSYNC_ACTIVE_F2_END__MASK;
}
#define REG_HDMI_TOTAL 0x000002c0
#define HDMI_TOTAL_H_TOTAL__MASK 0x00000fff
#define HDMI_TOTAL_H_TOTAL__SHIFT 0
static inline uint32_t HDMI_TOTAL_H_TOTAL(uint32_t val)
{
return ((val) << HDMI_TOTAL_H_TOTAL__SHIFT) & HDMI_TOTAL_H_TOTAL__MASK;
}
#define HDMI_TOTAL_V_TOTAL__MASK 0x0fff0000
#define HDMI_TOTAL_V_TOTAL__SHIFT 16
static inline uint32_t HDMI_TOTAL_V_TOTAL(uint32_t val)
{
return ((val) << HDMI_TOTAL_V_TOTAL__SHIFT) & HDMI_TOTAL_V_TOTAL__MASK;
}
#define REG_HDMI_VSYNC_TOTAL_F2 0x000002c4
#define HDMI_VSYNC_TOTAL_F2_V_TOTAL__MASK 0x00000fff
#define HDMI_VSYNC_TOTAL_F2_V_TOTAL__SHIFT 0
static inline uint32_t HDMI_VSYNC_TOTAL_F2_V_TOTAL(uint32_t val)
{
return ((val) << HDMI_VSYNC_TOTAL_F2_V_TOTAL__SHIFT) & HDMI_VSYNC_TOTAL_F2_V_TOTAL__MASK;
}
#define REG_HDMI_FRAME_CTRL 0x000002c8
#define HDMI_FRAME_CTRL_RGB_MUX_SEL_BGR 0x00001000
#define HDMI_FRAME_CTRL_VSYNC_LOW 0x10000000
#define HDMI_FRAME_CTRL_HSYNC_LOW 0x20000000
#define HDMI_FRAME_CTRL_INTERLACED_EN 0x80000000
#define REG_HDMI_AUD_INT 0x000002cc
#define HDMI_AUD_INT_AUD_FIFO_URUN_INT 0x00000001
#define HDMI_AUD_INT_AUD_FIFO_URAN_MASK 0x00000002
#define HDMI_AUD_INT_AUD_SAM_DROP_INT 0x00000004
#define HDMI_AUD_INT_AUD_SAM_DROP_MASK 0x00000008
#define REG_HDMI_PHY_CTRL 0x000002d4
#define HDMI_PHY_CTRL_SW_RESET_PLL 0x00000001
#define HDMI_PHY_CTRL_SW_RESET_PLL_LOW 0x00000002
#define HDMI_PHY_CTRL_SW_RESET 0x00000004
#define HDMI_PHY_CTRL_SW_RESET_LOW 0x00000008
#define REG_HDMI_CEC_WR_RANGE 0x000002dc
#define REG_HDMI_CEC_RD_RANGE 0x000002e0
#define REG_HDMI_VERSION 0x000002e4
#define REG_HDMI_CEC_COMPL_CTL 0x00000360
#define REG_HDMI_CEC_RD_START_RANGE 0x00000364
#define REG_HDMI_CEC_RD_TOTAL_RANGE 0x00000368
#define REG_HDMI_CEC_RD_ERR_RESP_LO 0x0000036c
#define REG_HDMI_CEC_WR_CHECK_CONFIG 0x00000370
#define REG_HDMI_8x60_PHY_REG0 0x00000300
#define HDMI_8x60_PHY_REG0_DESER_DEL_CTRL__MASK 0x0000001c
#define HDMI_8x60_PHY_REG0_DESER_DEL_CTRL__SHIFT 2
static inline uint32_t HDMI_8x60_PHY_REG0_DESER_DEL_CTRL(uint32_t val)
{
return ((val) << HDMI_8x60_PHY_REG0_DESER_DEL_CTRL__SHIFT) & HDMI_8x60_PHY_REG0_DESER_DEL_CTRL__MASK;
}
#define REG_HDMI_8x60_PHY_REG1 0x00000304
#define HDMI_8x60_PHY_REG1_DTEST_MUX_SEL__MASK 0x000000f0
#define HDMI_8x60_PHY_REG1_DTEST_MUX_SEL__SHIFT 4
static inline uint32_t HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(uint32_t val)
{
return ((val) << HDMI_8x60_PHY_REG1_DTEST_MUX_SEL__SHIFT) & HDMI_8x60_PHY_REG1_DTEST_MUX_SEL__MASK;
}
#define HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL__MASK 0x0000000f
#define HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL__SHIFT 0
static inline uint32_t HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(uint32_t val)
{
return ((val) << HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL__SHIFT) & HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL__MASK;
}
#define REG_HDMI_8x60_PHY_REG2 0x00000308
#define HDMI_8x60_PHY_REG2_PD_DESER 0x00000001
#define HDMI_8x60_PHY_REG2_PD_DRIVE_1 0x00000002
#define HDMI_8x60_PHY_REG2_PD_DRIVE_2 0x00000004
#define HDMI_8x60_PHY_REG2_PD_DRIVE_3 0x00000008
#define HDMI_8x60_PHY_REG2_PD_DRIVE_4 0x00000010
#define HDMI_8x60_PHY_REG2_PD_PLL 0x00000020
#define HDMI_8x60_PHY_REG2_PD_PWRGEN 0x00000040
#define HDMI_8x60_PHY_REG2_RCV_SENSE_EN 0x00000080
#define REG_HDMI_8x60_PHY_REG3 0x0000030c
#define HDMI_8x60_PHY_REG3_PLL_ENABLE 0x00000001
#define REG_HDMI_8x60_PHY_REG4 0x00000310
#define REG_HDMI_8x60_PHY_REG5 0x00000314
#define REG_HDMI_8x60_PHY_REG6 0x00000318
#define REG_HDMI_8x60_PHY_REG7 0x0000031c
#define REG_HDMI_8x60_PHY_REG8 0x00000320
#define REG_HDMI_8x60_PHY_REG9 0x00000324
#define REG_HDMI_8x60_PHY_REG10 0x00000328
#define REG_HDMI_8x60_PHY_REG11 0x0000032c
#define REG_HDMI_8x60_PHY_REG12 0x00000330
#define HDMI_8x60_PHY_REG12_RETIMING_EN 0x00000001
#define HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN 0x00000002
#define HDMI_8x60_PHY_REG12_FORCE_LOCK 0x00000010
#define REG_HDMI_8960_PHY_REG0 0x00000400
#define REG_HDMI_8960_PHY_REG1 0x00000404
#define REG_HDMI_8960_PHY_REG2 0x00000408
#define REG_HDMI_8960_PHY_REG3 0x0000040c
#define REG_HDMI_8960_PHY_REG4 0x00000410
#define REG_HDMI_8960_PHY_REG5 0x00000414
#define REG_HDMI_8960_PHY_REG6 0x00000418
#define REG_HDMI_8960_PHY_REG7 0x0000041c
#define REG_HDMI_8960_PHY_REG8 0x00000420
#define REG_HDMI_8960_PHY_REG9 0x00000424
#define REG_HDMI_8960_PHY_REG10 0x00000428
#define REG_HDMI_8960_PHY_REG11 0x0000042c
#define REG_HDMI_8960_PHY_REG12 0x00000430
#define HDMI_8960_PHY_REG12_SW_RESET 0x00000020
#define HDMI_8960_PHY_REG12_PWRDN_B 0x00000080
#define REG_HDMI_8960_PHY_REG_BIST_CFG 0x00000434
#define REG_HDMI_8960_PHY_DEBUG_BUS_SEL 0x00000438
#define REG_HDMI_8960_PHY_REG_MISC0 0x0000043c
#define REG_HDMI_8960_PHY_REG13 0x00000440
#define REG_HDMI_8960_PHY_REG14 0x00000444
#define REG_HDMI_8960_PHY_REG15 0x00000448
#define REG_HDMI_8960_PHY_PLL_REFCLK_CFG 0x00000500
#define REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG 0x00000504
#define REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 0x00000508
#define REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 0x0000050c
#define REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG 0x00000510
#define REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG 0x00000514
#define REG_HDMI_8960_PHY_PLL_PWRDN_B 0x00000518
#define HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL 0x00000002
#define HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B 0x00000008
#define REG_HDMI_8960_PHY_PLL_SDM_CFG0 0x0000051c
#define REG_HDMI_8960_PHY_PLL_SDM_CFG1 0x00000520
#define REG_HDMI_8960_PHY_PLL_SDM_CFG2 0x00000524
#define REG_HDMI_8960_PHY_PLL_SDM_CFG3 0x00000528
#define REG_HDMI_8960_PHY_PLL_SDM_CFG4 0x0000052c
#define REG_HDMI_8960_PHY_PLL_SSC_CFG0 0x00000530
#define REG_HDMI_8960_PHY_PLL_SSC_CFG1 0x00000534
#define REG_HDMI_8960_PHY_PLL_SSC_CFG2 0x00000538
#define REG_HDMI_8960_PHY_PLL_SSC_CFG3 0x0000053c
#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 0x00000540
#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 0x00000544
#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 0x00000548
#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 0x0000054c
#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 0x00000550
#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 0x00000554
#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 0x00000558
#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 0x0000055c
#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 0x00000560
#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 0x00000564
#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 0x00000568
#define REG_HDMI_8960_PHY_PLL_DEBUG_SEL 0x0000056c
#define REG_HDMI_8960_PHY_PLL_MISC0 0x00000570
#define REG_HDMI_8960_PHY_PLL_MISC1 0x00000574
#define REG_HDMI_8960_PHY_PLL_MISC2 0x00000578
#define REG_HDMI_8960_PHY_PLL_MISC3 0x0000057c
#define REG_HDMI_8960_PHY_PLL_MISC4 0x00000580
#define REG_HDMI_8960_PHY_PLL_MISC5 0x00000584
#define REG_HDMI_8960_PHY_PLL_MISC6 0x00000588
#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS0 0x0000058c
#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS1 0x00000590
#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS2 0x00000594
#define REG_HDMI_8960_PHY_PLL_STATUS0 0x00000598
#define HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK 0x00000001
#define REG_HDMI_8960_PHY_PLL_STATUS1 0x0000059c
#define REG_HDMI_8x74_ANA_CFG0 0x00000000
#define REG_HDMI_8x74_ANA_CFG1 0x00000004
#define REG_HDMI_8x74_PD_CTRL0 0x00000010
#define REG_HDMI_8x74_PD_CTRL1 0x00000014
#define REG_HDMI_8x74_BIST_CFG0 0x00000034
#define REG_HDMI_8x74_BIST_PATN0 0x0000003c
#define REG_HDMI_8x74_BIST_PATN1 0x00000040
#define REG_HDMI_8x74_BIST_PATN2 0x00000044
#define REG_HDMI_8x74_BIST_PATN3 0x00000048
#endif /* HDMI_XML */

View file

@ -0,0 +1,273 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/hdmi.h>
#include "hdmi.h"
/* Supported HDMI Audio channels */
#define MSM_HDMI_AUDIO_CHANNEL_2 0
#define MSM_HDMI_AUDIO_CHANNEL_4 1
#define MSM_HDMI_AUDIO_CHANNEL_6 2
#define MSM_HDMI_AUDIO_CHANNEL_8 3
/* maps MSM_HDMI_AUDIO_CHANNEL_n consts used by audio driver to # of channels: */
static int nchannels[] = { 2, 4, 6, 8 };
/* Supported HDMI Audio sample rates */
#define MSM_HDMI_SAMPLE_RATE_32KHZ 0
#define MSM_HDMI_SAMPLE_RATE_44_1KHZ 1
#define MSM_HDMI_SAMPLE_RATE_48KHZ 2
#define MSM_HDMI_SAMPLE_RATE_88_2KHZ 3
#define MSM_HDMI_SAMPLE_RATE_96KHZ 4
#define MSM_HDMI_SAMPLE_RATE_176_4KHZ 5
#define MSM_HDMI_SAMPLE_RATE_192KHZ 6
#define MSM_HDMI_SAMPLE_RATE_MAX 7
struct hdmi_msm_audio_acr {
uint32_t n; /* N parameter for clock regeneration */
uint32_t cts; /* CTS parameter for clock regeneration */
};
struct hdmi_msm_audio_arcs {
unsigned long int pixclock;
struct hdmi_msm_audio_acr lut[MSM_HDMI_SAMPLE_RATE_MAX];
};
#define HDMI_MSM_AUDIO_ARCS(pclk, ...) { (1000 * (pclk)), __VA_ARGS__ }
/* Audio constants lookup table for hdmi_msm_audio_acr_setup */
/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
static const struct hdmi_msm_audio_arcs acr_lut[] = {
/* 25.200MHz */
HDMI_MSM_AUDIO_ARCS(25200, {
{4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
{12288, 25200}, {25088, 28000}, {24576, 25200} }),
/* 27.000MHz */
HDMI_MSM_AUDIO_ARCS(27000, {
{4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
{12288, 27000}, {25088, 30000}, {24576, 27000} }),
/* 27.027MHz */
HDMI_MSM_AUDIO_ARCS(27030, {
{4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
{12288, 27027}, {25088, 30030}, {24576, 27027} }),
/* 74.250MHz */
HDMI_MSM_AUDIO_ARCS(74250, {
{4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
{12288, 74250}, {25088, 82500}, {24576, 74250} }),
/* 148.500MHz */
HDMI_MSM_AUDIO_ARCS(148500, {
{4096, 148500}, {6272, 165000}, {6144, 148500}, {12544, 165000},
{12288, 148500}, {25088, 165000}, {24576, 148500} }),
};
static const struct hdmi_msm_audio_arcs *get_arcs(unsigned long int pixclock)
{
int i;
for (i = 0; i < ARRAY_SIZE(acr_lut); i++) {
const struct hdmi_msm_audio_arcs *arcs = &acr_lut[i];
if (arcs->pixclock == pixclock)
return arcs;
}
return NULL;
}
int hdmi_audio_update(struct hdmi *hdmi)
{
struct hdmi_audio *audio = &hdmi->audio;
struct hdmi_audio_infoframe *info = &audio->infoframe;
const struct hdmi_msm_audio_arcs *arcs = NULL;
bool enabled = audio->enabled;
uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl;
uint32_t infofrm_ctrl, audio_config;
DBG("audio: enabled=%d, channels=%d, channel_allocation=0x%x, "
"level_shift_value=%d, downmix_inhibit=%d, rate=%d",
audio->enabled, info->channels, info->channel_allocation,
info->level_shift_value, info->downmix_inhibit, audio->rate);
DBG("video: power_on=%d, pixclock=%lu", hdmi->power_on, hdmi->pixclock);
if (enabled && !(hdmi->power_on && hdmi->pixclock)) {
DBG("disabling audio: no video");
enabled = false;
}
if (enabled) {
arcs = get_arcs(hdmi->pixclock);
if (!arcs) {
DBG("disabling audio: unsupported pixclock: %lu",
hdmi->pixclock);
enabled = false;
}
}
/* Read first before writing */
acr_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_ACR_PKT_CTRL);
vbi_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL);
aud_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_AUDIO_PKT_CTRL1);
infofrm_ctrl = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
audio_config = hdmi_read(hdmi, REG_HDMI_AUDIO_CFG);
/* Clear N/CTS selection bits */
acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SELECT__MASK;
if (enabled) {
uint32_t n, cts, multiplier;
enum hdmi_acr_cts select;
uint8_t buf[14];
n = arcs->lut[audio->rate].n;
cts = arcs->lut[audio->rate].cts;
if ((MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate) ||
(MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate)) {
multiplier = 4;
n >>= 2; /* divide N by 4 and use multiplier */
} else if ((MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) ||
(MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate)) {
multiplier = 2;
n >>= 1; /* divide N by 2 and use multiplier */
} else {
multiplier = 1;
}
DBG("n=%u, cts=%u, multiplier=%u", n, cts, multiplier);
acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SOURCE;
acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_AUDIO_PRIORITY;
acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_N_MULTIPLIER(multiplier);
if ((MSM_HDMI_SAMPLE_RATE_48KHZ == audio->rate) ||
(MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) ||
(MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate))
select = ACR_48;
else if ((MSM_HDMI_SAMPLE_RATE_44_1KHZ == audio->rate) ||
(MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate) ||
(MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate))
select = ACR_44;
else /* default to 32k */
select = ACR_32;
acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SELECT(select);
hdmi_write(hdmi, REG_HDMI_ACR_0(select - 1),
HDMI_ACR_0_CTS(cts));
hdmi_write(hdmi, REG_HDMI_ACR_1(select - 1),
HDMI_ACR_1_N(n));
hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL2,
COND(info->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) |
HDMI_AUDIO_PKT_CTRL2_OVERRIDE);
acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_CONT;
acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SEND;
/* configure infoframe: */
hdmi_audio_infoframe_pack(info, buf, sizeof(buf));
hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0,
(buf[3] << 0) || (buf[4] << 8) ||
(buf[5] << 16) || (buf[6] << 24));
hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1,
(buf[7] << 0) || (buf[8] << 8));
hdmi_write(hdmi, REG_HDMI_GC, 0);
vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_ENABLE;
vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME;
aud_pkt_ctrl |= HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND;
infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND;
infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT;
infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE;
infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
audio_config &= ~HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK;
audio_config |= HDMI_AUDIO_CFG_FIFO_WATERMARK(4);
audio_config |= HDMI_AUDIO_CFG_ENGINE_ENABLE;
} else {
hdmi_write(hdmi, REG_HDMI_GC, HDMI_GC_MUTE);
acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_CONT;
acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SEND;
vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_ENABLE;
vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME;
aud_pkt_ctrl &= ~HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND;
infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND;
infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT;
infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE;
infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
audio_config &= ~HDMI_AUDIO_CFG_ENGINE_ENABLE;
}
hdmi_write(hdmi, REG_HDMI_ACR_PKT_CTRL, acr_pkt_ctrl);
hdmi_write(hdmi, REG_HDMI_VBI_PKT_CTRL, vbi_pkt_ctrl);
hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL1, aud_pkt_ctrl);
hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, infofrm_ctrl);
hdmi_write(hdmi, REG_HDMI_AUD_INT,
COND(enabled, HDMI_AUD_INT_AUD_FIFO_URUN_INT) |
COND(enabled, HDMI_AUD_INT_AUD_SAM_DROP_INT));
hdmi_write(hdmi, REG_HDMI_AUDIO_CFG, audio_config);
DBG("audio %sabled", enabled ? "en" : "dis");
return 0;
}
int hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,
uint32_t num_of_channels, uint32_t channel_allocation,
uint32_t level_shift, bool down_mix)
{
struct hdmi_audio *audio;
if (!hdmi)
return -ENXIO;
audio = &hdmi->audio;
if (num_of_channels >= ARRAY_SIZE(nchannels))
return -EINVAL;
audio->enabled = enabled;
audio->infoframe.channels = nchannels[num_of_channels];
audio->infoframe.channel_allocation = channel_allocation;
audio->infoframe.level_shift_value = level_shift;
audio->infoframe.downmix_inhibit = down_mix;
return hdmi_audio_update(hdmi);
}
void hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate)
{
struct hdmi_audio *audio;
if (!hdmi)
return;
audio = &hdmi->audio;
if ((rate < 0) || (rate >= MSM_HDMI_SAMPLE_RATE_MAX))
return;
audio->rate = rate;
hdmi_audio_update(hdmi);
}

View file

@ -0,0 +1,234 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "hdmi.h"
struct hdmi_bridge {
struct drm_bridge base;
struct hdmi *hdmi;
};
#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
static void hdmi_bridge_destroy(struct drm_bridge *bridge)
{
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
hdmi_unreference(hdmi_bridge->hdmi);
drm_bridge_cleanup(bridge);
kfree(hdmi_bridge);
}
static void power_on(struct drm_bridge *bridge)
{
struct drm_device *dev = bridge->dev;
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
const struct hdmi_platform_config *config = hdmi->config;
int i, ret;
for (i = 0; i < config->pwr_reg_cnt; i++) {
ret = regulator_enable(hdmi->pwr_regs[i]);
if (ret) {
dev_err(dev->dev, "failed to enable pwr regulator: %s (%d)\n",
config->pwr_reg_names[i], ret);
}
}
if (config->pwr_clk_cnt > 0) {
DBG("pixclock: %lu", hdmi->pixclock);
ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock);
if (ret) {
dev_err(dev->dev, "failed to set pixel clk: %s (%d)\n",
config->pwr_clk_names[0], ret);
}
}
for (i = 0; i < config->pwr_clk_cnt; i++) {
ret = clk_prepare_enable(hdmi->pwr_clks[i]);
if (ret) {
dev_err(dev->dev, "failed to enable pwr clk: %s (%d)\n",
config->pwr_clk_names[i], ret);
}
}
}
static void power_off(struct drm_bridge *bridge)
{
struct drm_device *dev = bridge->dev;
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
const struct hdmi_platform_config *config = hdmi->config;
int i, ret;
/* TODO do we need to wait for final vblank somewhere before
* cutting the clocks?
*/
mdelay(16 + 4);
for (i = 0; i < config->pwr_clk_cnt; i++)
clk_disable_unprepare(hdmi->pwr_clks[i]);
for (i = 0; i < config->pwr_reg_cnt; i++) {
ret = regulator_disable(hdmi->pwr_regs[i]);
if (ret) {
dev_err(dev->dev, "failed to disable pwr regulator: %s (%d)\n",
config->pwr_reg_names[i], ret);
}
}
}
static void hdmi_bridge_pre_enable(struct drm_bridge *bridge)
{
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
struct hdmi_phy *phy = hdmi->phy;
DBG("power up");
if (!hdmi->power_on) {
power_on(bridge);
hdmi->power_on = true;
hdmi_audio_update(hdmi);
}
phy->funcs->powerup(phy, hdmi->pixclock);
hdmi_set_mode(hdmi, true);
}
static void hdmi_bridge_enable(struct drm_bridge *bridge)
{
}
static void hdmi_bridge_disable(struct drm_bridge *bridge)
{
}
static void hdmi_bridge_post_disable(struct drm_bridge *bridge)
{
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
struct hdmi_phy *phy = hdmi->phy;
DBG("power down");
hdmi_set_mode(hdmi, false);
phy->funcs->powerdown(phy);
if (hdmi->power_on) {
power_off(bridge);
hdmi->power_on = false;
hdmi_audio_update(hdmi);
}
}
static void hdmi_bridge_mode_set(struct drm_bridge *bridge,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
int hstart, hend, vstart, vend;
uint32_t frame_ctrl;
mode = adjusted_mode;
hdmi->pixclock = mode->clock * 1000;
hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1;
hstart = mode->htotal - mode->hsync_start;
hend = mode->htotal - mode->hsync_start + mode->hdisplay;
vstart = mode->vtotal - mode->vsync_start - 1;
vend = mode->vtotal - mode->vsync_start + mode->vdisplay - 1;
DBG("htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d",
mode->htotal, mode->vtotal, hstart, hend, vstart, vend);
hdmi_write(hdmi, REG_HDMI_TOTAL,
HDMI_TOTAL_H_TOTAL(mode->htotal - 1) |
HDMI_TOTAL_V_TOTAL(mode->vtotal - 1));
hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC,
HDMI_ACTIVE_HSYNC_START(hstart) |
HDMI_ACTIVE_HSYNC_END(hend));
hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC,
HDMI_ACTIVE_VSYNC_START(vstart) |
HDMI_ACTIVE_VSYNC_END(vend));
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal));
hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) |
HDMI_VSYNC_ACTIVE_F2_END(vend + 1));
} else {
hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
HDMI_VSYNC_TOTAL_F2_V_TOTAL(0));
hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
HDMI_VSYNC_ACTIVE_F2_START(0) |
HDMI_VSYNC_ACTIVE_F2_END(0));
}
frame_ctrl = 0;
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW;
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN;
DBG("frame_ctrl=%08x", frame_ctrl);
hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);
hdmi_audio_update(hdmi);
}
static const struct drm_bridge_funcs hdmi_bridge_funcs = {
.pre_enable = hdmi_bridge_pre_enable,
.enable = hdmi_bridge_enable,
.disable = hdmi_bridge_disable,
.post_disable = hdmi_bridge_post_disable,
.mode_set = hdmi_bridge_mode_set,
.destroy = hdmi_bridge_destroy,
};
/* initialize bridge */
struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi)
{
struct drm_bridge *bridge = NULL;
struct hdmi_bridge *hdmi_bridge;
int ret;
hdmi_bridge = kzalloc(sizeof(*hdmi_bridge), GFP_KERNEL);
if (!hdmi_bridge) {
ret = -ENOMEM;
goto fail;
}
hdmi_bridge->hdmi = hdmi_reference(hdmi);
bridge = &hdmi_bridge->base;
drm_bridge_init(hdmi->dev, bridge, &hdmi_bridge_funcs);
return bridge;
fail:
if (bridge)
hdmi_bridge_destroy(bridge);
return ERR_PTR(ret);
}

View file

@ -0,0 +1,457 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/gpio.h>
#include "msm_kms.h"
#include "hdmi.h"
struct hdmi_connector {
struct drm_connector base;
struct hdmi *hdmi;
struct work_struct hpd_work;
};
#define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base)
static int gpio_config(struct hdmi *hdmi, bool on)
{
struct drm_device *dev = hdmi->dev;
const struct hdmi_platform_config *config = hdmi->config;
int ret;
if (on) {
ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK");
if (ret) {
dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_DDC_CLK", config->ddc_clk_gpio, ret);
goto error1;
}
gpio_set_value_cansleep(config->ddc_clk_gpio, 1);
ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA");
if (ret) {
dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_DDC_DATA", config->ddc_data_gpio, ret);
goto error2;
}
gpio_set_value_cansleep(config->ddc_data_gpio, 1);
ret = gpio_request(config->hpd_gpio, "HDMI_HPD");
if (ret) {
dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_HPD", config->hpd_gpio, ret);
goto error3;
}
gpio_direction_input(config->hpd_gpio);
gpio_set_value_cansleep(config->hpd_gpio, 1);
if (config->mux_en_gpio != -1) {
ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");
if (ret) {
dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_MUX_EN", config->mux_en_gpio, ret);
goto error4;
}
gpio_set_value_cansleep(config->mux_en_gpio, 1);
}
if (config->mux_sel_gpio != -1) {
ret = gpio_request(config->mux_sel_gpio, "HDMI_MUX_SEL");
if (ret) {
dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_MUX_SEL", config->mux_sel_gpio, ret);
goto error5;
}
gpio_set_value_cansleep(config->mux_sel_gpio, 0);
}
if (config->mux_lpm_gpio != -1) {
ret = gpio_request(config->mux_lpm_gpio,
"HDMI_MUX_LPM");
if (ret) {
dev_err(dev->dev,
"'%s'(%d) gpio_request failed: %d\n",
"HDMI_MUX_LPM",
config->mux_lpm_gpio, ret);
goto error6;
}
gpio_set_value_cansleep(config->mux_lpm_gpio, 1);
}
DBG("gpio on");
} else {
gpio_free(config->ddc_clk_gpio);
gpio_free(config->ddc_data_gpio);
gpio_free(config->hpd_gpio);
if (config->mux_en_gpio != -1) {
gpio_set_value_cansleep(config->mux_en_gpio, 0);
gpio_free(config->mux_en_gpio);
}
if (config->mux_sel_gpio != -1) {
gpio_set_value_cansleep(config->mux_sel_gpio, 1);
gpio_free(config->mux_sel_gpio);
}
if (config->mux_lpm_gpio != -1) {
gpio_set_value_cansleep(config->mux_lpm_gpio, 0);
gpio_free(config->mux_lpm_gpio);
}
DBG("gpio off");
}
return 0;
error6:
if (config->mux_sel_gpio != -1)
gpio_free(config->mux_sel_gpio);
error5:
if (config->mux_en_gpio != -1)
gpio_free(config->mux_en_gpio);
error4:
gpio_free(config->hpd_gpio);
error3:
gpio_free(config->ddc_data_gpio);
error2:
gpio_free(config->ddc_clk_gpio);
error1:
return ret;
}
static int hpd_enable(struct hdmi_connector *hdmi_connector)
{
struct hdmi *hdmi = hdmi_connector->hdmi;
const struct hdmi_platform_config *config = hdmi->config;
struct drm_device *dev = hdmi_connector->base.dev;
struct hdmi_phy *phy = hdmi->phy;
uint32_t hpd_ctrl;
int i, ret;
ret = gpio_config(hdmi, true);
if (ret) {
dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret);
goto fail;
}
for (i = 0; i < config->hpd_clk_cnt; i++) {
if (config->hpd_freq && config->hpd_freq[i]) {
ret = clk_set_rate(hdmi->hpd_clks[i],
config->hpd_freq[i]);
if (ret)
dev_warn(dev->dev, "failed to set clk %s (%d)\n",
config->hpd_clk_names[i], ret);
}
ret = clk_prepare_enable(hdmi->hpd_clks[i]);
if (ret) {
dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n",
config->hpd_clk_names[i], ret);
goto fail;
}
}
for (i = 0; i < config->hpd_reg_cnt; i++) {
ret = regulator_enable(hdmi->hpd_regs[i]);
if (ret) {
dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n",
config->hpd_reg_names[i], ret);
goto fail;
}
}
hdmi_set_mode(hdmi, false);
phy->funcs->reset(phy);
hdmi_set_mode(hdmi, true);
hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b);
/* enable HPD events: */
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
HDMI_HPD_INT_CTRL_INT_CONNECT |
HDMI_HPD_INT_CTRL_INT_EN);
/* set timeout to 4.1ms (max) for hardware debounce */
hpd_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_CTRL);
hpd_ctrl |= HDMI_HPD_CTRL_TIMEOUT(0x1fff);
/* Toggle HPD circuit to trigger HPD sense */
hdmi_write(hdmi, REG_HDMI_HPD_CTRL,
~HDMI_HPD_CTRL_ENABLE & hpd_ctrl);
hdmi_write(hdmi, REG_HDMI_HPD_CTRL,
HDMI_HPD_CTRL_ENABLE | hpd_ctrl);
return 0;
fail:
return ret;
}
static int hdp_disable(struct hdmi_connector *hdmi_connector)
{
struct hdmi *hdmi = hdmi_connector->hdmi;
const struct hdmi_platform_config *config = hdmi->config;
struct drm_device *dev = hdmi_connector->base.dev;
int i, ret = 0;
/* Disable HPD interrupt */
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
hdmi_set_mode(hdmi, false);
for (i = 0; i < config->hpd_reg_cnt; i++) {
ret = regulator_disable(hdmi->hpd_regs[i]);
if (ret) {
dev_err(dev->dev, "failed to disable hpd regulator: %s (%d)\n",
config->hpd_reg_names[i], ret);
goto fail;
}
}
for (i = 0; i < config->hpd_clk_cnt; i++)
clk_disable_unprepare(hdmi->hpd_clks[i]);
ret = gpio_config(hdmi, false);
if (ret) {
dev_err(dev->dev, "failed to unconfigure GPIOs: %d\n", ret);
goto fail;
}
return 0;
fail:
return ret;
}
static void
hotplug_work(struct work_struct *work)
{
struct hdmi_connector *hdmi_connector =
container_of(work, struct hdmi_connector, hpd_work);
struct drm_connector *connector = &hdmi_connector->base;
drm_helper_hpd_irq_event(connector->dev);
}
void hdmi_connector_irq(struct drm_connector *connector)
{
struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
struct msm_drm_private *priv = connector->dev->dev_private;
struct hdmi *hdmi = hdmi_connector->hdmi;
uint32_t hpd_int_status, hpd_int_ctrl;
/* Process HPD: */
hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
hpd_int_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_INT_CTRL);
if ((hpd_int_ctrl & HDMI_HPD_INT_CTRL_INT_EN) &&
(hpd_int_status & HDMI_HPD_INT_STATUS_INT)) {
bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED);
DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl);
/* ack the irq: */
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
hpd_int_ctrl | HDMI_HPD_INT_CTRL_INT_ACK);
/* detect disconnect if we are connected or visa versa: */
hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN;
if (!detected)
hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
queue_work(priv->wq, &hdmi_connector->hpd_work);
}
}
static enum drm_connector_status detect_reg(struct hdmi *hdmi)
{
uint32_t hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ?
connector_status_connected : connector_status_disconnected;
}
static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
{
const struct hdmi_platform_config *config = hdmi->config;
return gpio_get_value(config->hpd_gpio) ?
connector_status_connected :
connector_status_disconnected;
}
static enum drm_connector_status hdmi_connector_detect(
struct drm_connector *connector, bool force)
{
struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
struct hdmi *hdmi = hdmi_connector->hdmi;
enum drm_connector_status stat_gpio, stat_reg;
int retry = 20;
do {
stat_gpio = detect_gpio(hdmi);
stat_reg = detect_reg(hdmi);
if (stat_gpio == stat_reg)
break;
mdelay(10);
} while (--retry);
/* the status we get from reading gpio seems to be more reliable,
* so trust that one the most if we didn't manage to get hdmi and
* gpio status to agree:
*/
if (stat_gpio != stat_reg) {
DBG("HDMI_HPD_INT_STATUS tells us: %d", stat_reg);
DBG("hpd gpio tells us: %d", stat_gpio);
}
return stat_gpio;
}
static void hdmi_connector_destroy(struct drm_connector *connector)
{
struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
hdp_disable(hdmi_connector);
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
hdmi_unreference(hdmi_connector->hdmi);
kfree(hdmi_connector);
}
static int hdmi_connector_get_modes(struct drm_connector *connector)
{
struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
struct hdmi *hdmi = hdmi_connector->hdmi;
struct edid *edid;
uint32_t hdmi_ctrl;
int ret = 0;
hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
edid = drm_get_edid(connector, hdmi->i2c);
hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
drm_mode_connector_update_edid_property(connector, edid);
if (edid) {
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}
return ret;
}
static int hdmi_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
struct hdmi *hdmi = hdmi_connector->hdmi;
const struct hdmi_platform_config *config = hdmi->config;
struct msm_drm_private *priv = connector->dev->dev_private;
struct msm_kms *kms = priv->kms;
long actual, requested;
requested = 1000 * mode->clock;
actual = kms->funcs->round_pixclk(kms,
requested, hdmi_connector->hdmi->encoder);
/* for mdp5/apq8074, we manage our own pixel clk (as opposed to
* mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
* instead):
*/
if (config->pwr_clk_cnt > 0)
actual = clk_round_rate(hdmi->pwr_clks[0], actual);
DBG("requested=%ld, actual=%ld", requested, actual);
if (actual != requested)
return MODE_CLOCK_RANGE;
return 0;
}
static struct drm_encoder *
hdmi_connector_best_encoder(struct drm_connector *connector)
{
struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
return hdmi_connector->hdmi->encoder;
}
static const struct drm_connector_funcs hdmi_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = hdmi_connector_destroy,
};
static const struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
.get_modes = hdmi_connector_get_modes,
.mode_valid = hdmi_connector_mode_valid,
.best_encoder = hdmi_connector_best_encoder,
};
/* initialize connector */
struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
{
struct drm_connector *connector = NULL;
struct hdmi_connector *hdmi_connector;
int ret;
hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
if (!hdmi_connector) {
ret = -ENOMEM;
goto fail;
}
hdmi_connector->hdmi = hdmi_reference(hdmi);
INIT_WORK(&hdmi_connector->hpd_work, hotplug_work);
connector = &hdmi_connector->base;
drm_connector_init(hdmi->dev, connector, &hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
connector->interlace_allowed = 1;
connector->doublescan_allowed = 0;
drm_connector_register(connector);
ret = hpd_enable(hdmi_connector);
if (ret) {
dev_err(hdmi->dev->dev, "failed to enable HPD: %d\n", ret);
goto fail;
}
drm_mode_connector_attach_encoder(connector, hdmi->encoder);
return connector;
fail:
if (connector)
hdmi_connector_destroy(connector);
return ERR_PTR(ret);
}

View file

@ -0,0 +1,281 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "hdmi.h"
struct hdmi_i2c_adapter {
struct i2c_adapter base;
struct hdmi *hdmi;
bool sw_done;
wait_queue_head_t ddc_event;
};
#define to_hdmi_i2c_adapter(x) container_of(x, struct hdmi_i2c_adapter, base)
static void init_ddc(struct hdmi_i2c_adapter *hdmi_i2c)
{
struct hdmi *hdmi = hdmi_i2c->hdmi;
hdmi_write(hdmi, REG_HDMI_DDC_CTRL,
HDMI_DDC_CTRL_SW_STATUS_RESET);
hdmi_write(hdmi, REG_HDMI_DDC_CTRL,
HDMI_DDC_CTRL_SOFT_RESET);
hdmi_write(hdmi, REG_HDMI_DDC_SPEED,
HDMI_DDC_SPEED_THRESHOLD(2) |
HDMI_DDC_SPEED_PRESCALE(10));
hdmi_write(hdmi, REG_HDMI_DDC_SETUP,
HDMI_DDC_SETUP_TIMEOUT(0xff));
/* enable reference timer for 27us */
hdmi_write(hdmi, REG_HDMI_DDC_REF,
HDMI_DDC_REF_REFTIMER_ENABLE |
HDMI_DDC_REF_REFTIMER(27));
}
static int ddc_clear_irq(struct hdmi_i2c_adapter *hdmi_i2c)
{
struct hdmi *hdmi = hdmi_i2c->hdmi;
struct drm_device *dev = hdmi->dev;
uint32_t retry = 0xffff;
uint32_t ddc_int_ctrl;
do {
--retry;
hdmi_write(hdmi, REG_HDMI_DDC_INT_CTRL,
HDMI_DDC_INT_CTRL_SW_DONE_ACK |
HDMI_DDC_INT_CTRL_SW_DONE_MASK);
ddc_int_ctrl = hdmi_read(hdmi, REG_HDMI_DDC_INT_CTRL);
} while ((ddc_int_ctrl & HDMI_DDC_INT_CTRL_SW_DONE_INT) && retry);
if (!retry) {
dev_err(dev->dev, "timeout waiting for DDC\n");
return -ETIMEDOUT;
}
hdmi_i2c->sw_done = false;
return 0;
}
#define MAX_TRANSACTIONS 4
static bool sw_done(struct hdmi_i2c_adapter *hdmi_i2c)
{
struct hdmi *hdmi = hdmi_i2c->hdmi;
if (!hdmi_i2c->sw_done) {
uint32_t ddc_int_ctrl;
ddc_int_ctrl = hdmi_read(hdmi, REG_HDMI_DDC_INT_CTRL);
if ((ddc_int_ctrl & HDMI_DDC_INT_CTRL_SW_DONE_MASK) &&
(ddc_int_ctrl & HDMI_DDC_INT_CTRL_SW_DONE_INT)) {
hdmi_i2c->sw_done = true;
hdmi_write(hdmi, REG_HDMI_DDC_INT_CTRL,
HDMI_DDC_INT_CTRL_SW_DONE_ACK);
}
}
return hdmi_i2c->sw_done;
}
static int hdmi_i2c_xfer(struct i2c_adapter *i2c,
struct i2c_msg *msgs, int num)
{
struct hdmi_i2c_adapter *hdmi_i2c = to_hdmi_i2c_adapter(i2c);
struct hdmi *hdmi = hdmi_i2c->hdmi;
struct drm_device *dev = hdmi->dev;
static const uint32_t nack[] = {
HDMI_DDC_SW_STATUS_NACK0, HDMI_DDC_SW_STATUS_NACK1,
HDMI_DDC_SW_STATUS_NACK2, HDMI_DDC_SW_STATUS_NACK3,
};
int indices[MAX_TRANSACTIONS];
int ret, i, j, index = 0;
uint32_t ddc_status, ddc_data, i2c_trans;
num = min(num, MAX_TRANSACTIONS);
WARN_ON(!(hdmi_read(hdmi, REG_HDMI_CTRL) & HDMI_CTRL_ENABLE));
if (num == 0)
return num;
init_ddc(hdmi_i2c);
ret = ddc_clear_irq(hdmi_i2c);
if (ret)
return ret;
for (i = 0; i < num; i++) {
struct i2c_msg *p = &msgs[i];
uint32_t raw_addr = p->addr << 1;
if (p->flags & I2C_M_RD)
raw_addr |= 1;
ddc_data = HDMI_DDC_DATA_DATA(raw_addr) |
HDMI_DDC_DATA_DATA_RW(DDC_WRITE);
if (i == 0) {
ddc_data |= HDMI_DDC_DATA_INDEX(0) |
HDMI_DDC_DATA_INDEX_WRITE;
}
hdmi_write(hdmi, REG_HDMI_DDC_DATA, ddc_data);
index++;
indices[i] = index;
if (p->flags & I2C_M_RD) {
index += p->len;
} else {
for (j = 0; j < p->len; j++) {
ddc_data = HDMI_DDC_DATA_DATA(p->buf[j]) |
HDMI_DDC_DATA_DATA_RW(DDC_WRITE);
hdmi_write(hdmi, REG_HDMI_DDC_DATA, ddc_data);
index++;
}
}
i2c_trans = HDMI_I2C_TRANSACTION_REG_CNT(p->len) |
HDMI_I2C_TRANSACTION_REG_RW(
(p->flags & I2C_M_RD) ? DDC_READ : DDC_WRITE) |
HDMI_I2C_TRANSACTION_REG_START;
if (i == (num - 1))
i2c_trans |= HDMI_I2C_TRANSACTION_REG_STOP;
hdmi_write(hdmi, REG_HDMI_I2C_TRANSACTION(i), i2c_trans);
}
/* trigger the transfer: */
hdmi_write(hdmi, REG_HDMI_DDC_CTRL,
HDMI_DDC_CTRL_TRANSACTION_CNT(num - 1) |
HDMI_DDC_CTRL_GO);
ret = wait_event_timeout(hdmi_i2c->ddc_event, sw_done(hdmi_i2c), HZ/4);
if (ret <= 0) {
if (ret == 0)
ret = -ETIMEDOUT;
dev_warn(dev->dev, "DDC timeout: %d\n", ret);
DBG("sw_status=%08x, hw_status=%08x, int_ctrl=%08x",
hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS),
hdmi_read(hdmi, REG_HDMI_DDC_HW_STATUS),
hdmi_read(hdmi, REG_HDMI_DDC_INT_CTRL));
return ret;
}
ddc_status = hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS);
/* read back results of any read transactions: */
for (i = 0; i < num; i++) {
struct i2c_msg *p = &msgs[i];
if (!(p->flags & I2C_M_RD))
continue;
/* check for NACK: */
if (ddc_status & nack[i]) {
DBG("ddc_status=%08x", ddc_status);
break;
}
ddc_data = HDMI_DDC_DATA_DATA_RW(DDC_READ) |
HDMI_DDC_DATA_INDEX(indices[i]) |
HDMI_DDC_DATA_INDEX_WRITE;
hdmi_write(hdmi, REG_HDMI_DDC_DATA, ddc_data);
/* discard first byte: */
hdmi_read(hdmi, REG_HDMI_DDC_DATA);
for (j = 0; j < p->len; j++) {
ddc_data = hdmi_read(hdmi, REG_HDMI_DDC_DATA);
p->buf[j] = FIELD(ddc_data, HDMI_DDC_DATA_DATA);
}
}
return i;
}
static u32 hdmi_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm hdmi_i2c_algorithm = {
.master_xfer = hdmi_i2c_xfer,
.functionality = hdmi_i2c_func,
};
void hdmi_i2c_irq(struct i2c_adapter *i2c)
{
struct hdmi_i2c_adapter *hdmi_i2c = to_hdmi_i2c_adapter(i2c);
if (sw_done(hdmi_i2c))
wake_up_all(&hdmi_i2c->ddc_event);
}
void hdmi_i2c_destroy(struct i2c_adapter *i2c)
{
struct hdmi_i2c_adapter *hdmi_i2c = to_hdmi_i2c_adapter(i2c);
i2c_del_adapter(i2c);
kfree(hdmi_i2c);
}
struct i2c_adapter *hdmi_i2c_init(struct hdmi *hdmi)
{
struct drm_device *dev = hdmi->dev;
struct hdmi_i2c_adapter *hdmi_i2c;
struct i2c_adapter *i2c = NULL;
int ret;
hdmi_i2c = kzalloc(sizeof(*hdmi_i2c), GFP_KERNEL);
if (!hdmi_i2c) {
ret = -ENOMEM;
goto fail;
}
i2c = &hdmi_i2c->base;
hdmi_i2c->hdmi = hdmi;
init_waitqueue_head(&hdmi_i2c->ddc_event);
i2c->owner = THIS_MODULE;
i2c->class = I2C_CLASS_DDC;
snprintf(i2c->name, sizeof(i2c->name), "msm hdmi i2c");
i2c->dev.parent = &hdmi->pdev->dev;
i2c->algo = &hdmi_i2c_algorithm;
ret = i2c_add_adapter(i2c);
if (ret) {
dev_err(dev->dev, "failed to register hdmi i2c: %d\n", ret);
goto fail;
}
return i2c;
fail:
if (i2c)
hdmi_i2c_destroy(i2c);
return ERR_PTR(ret);
}

View file

@ -0,0 +1,527 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef CONFIG_COMMON_CLK
#include <linux/clk.h>
#include <linux/clk-provider.h>
#endif
#include "hdmi.h"
struct hdmi_phy_8960 {
struct hdmi_phy base;
struct hdmi *hdmi;
#ifdef CONFIG_COMMON_CLK
struct clk_hw pll_hw;
struct clk *pll;
unsigned long pixclk;
#endif
};
#define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base)
#ifdef CONFIG_COMMON_CLK
#define clk_to_phy(x) container_of(x, struct hdmi_phy_8960, pll_hw)
/*
* HDMI PLL:
*
* To get the parent clock setup properly, we need to plug in hdmi pll
* configuration into common-clock-framework.
*/
struct pll_rate {
unsigned long rate;
struct {
uint32_t val;
uint32_t reg;
} conf[32];
};
/* NOTE: keep sorted highest freq to lowest: */
static const struct pll_rate freqtbl[] = {
/* 1080p60/1080p50 case */
{ 148500000, {
{ 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
{ 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
{ 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
{ 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
{ 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
{ 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
{ 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
{ 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
{ 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
{ 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
{ 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
{ 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
{ 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
{ 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
{ 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
{ 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
{ 0, 0 } }
},
{ 108000000, {
{ 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
{ 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
{ 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
{ 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
{ 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
{ 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
{ 0, 0 } }
},
/* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */
{ 74250000, {
{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
{ 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
{ 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
{ 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
{ 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
{ 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
{ 0, 0 } }
},
{ 65000000, {
{ 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
{ 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
{ 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
{ 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
{ 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
{ 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
{ 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
{ 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
{ 0, 0 } }
},
/* 480p60/480i60 */
{ 27030000, {
{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
{ 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
{ 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
{ 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
{ 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
{ 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
{ 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
{ 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
{ 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
{ 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
{ 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
{ 0, 0 } }
},
/* 576p50/576i50 */
{ 27000000, {
{ 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
{ 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
{ 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
{ 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
{ 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
{ 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
{ 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
{ 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
{ 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
{ 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
{ 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
{ 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
{ 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
{ 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
{ 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
{ 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
{ 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
{ 0, 0 } }
},
/* 640x480p60 */
{ 25200000, {
{ 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
{ 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
{ 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
{ 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
{ 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
{ 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
{ 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
{ 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
{ 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
{ 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
{ 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
{ 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
{ 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
{ 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
{ 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
{ 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
{ 0, 0 } }
},
};
static int hdmi_pll_enable(struct clk_hw *hw)
{
struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
struct hdmi *hdmi = phy_8960->hdmi;
int timeout_count, pll_lock_retry = 10;
unsigned int val;
DBG("");
/* Assert PLL S/W reset */
hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10);
hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a);
/* Wait for a short time before de-asserting
* to allow the hardware to complete its job.
* This much of delay should be fine for hardware
* to assert and de-assert.
*/
udelay(10);
/* De-assert PLL S/W reset */
hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
val |= HDMI_8960_PHY_REG12_SW_RESET;
/* Assert PHY S/W reset */
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
val &= ~HDMI_8960_PHY_REG12_SW_RESET;
/* Wait for a short time before de-asserting
to allow the hardware to complete its job.
This much of delay should be fine for hardware
to assert and de-assert. */
udelay(10);
/* De-assert PHY S/W reset */
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x3f);
val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
val |= HDMI_8960_PHY_REG12_PWRDN_B;
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
/* Wait 10 us for enabling global power for PHY */
mb();
udelay(10);
val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B);
val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B;
val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL;
hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x80);
timeout_count = 1000;
while (--pll_lock_retry > 0) {
/* are we there yet? */
val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_STATUS0);
if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK)
break;
udelay(1);
if (--timeout_count > 0)
continue;
/*
* PLL has still not locked.
* Do a software reset and try again
* Assert PLL S/W reset first
*/
hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
udelay(10);
hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
/*
* Wait for a short duration for the PLL calibration
* before checking if the PLL gets locked
*/
udelay(350);
timeout_count = 1000;
}
return 0;
}
static void hdmi_pll_disable(struct clk_hw *hw)
{
struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
struct hdmi *hdmi = phy_8960->hdmi;
unsigned int val;
DBG("");
val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B);
val |= HDMI_8960_PHY_REG12_SW_RESET;
val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
/* Make sure HDMI PHY/PLL are powered down */
mb();
}
static const struct pll_rate *find_rate(unsigned long rate)
{
int i;
for (i = 1; i < ARRAY_SIZE(freqtbl); i++)
if (rate > freqtbl[i].rate)
return &freqtbl[i-1];
return &freqtbl[i-1];
}
static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
return phy_8960->pixclk;
}
static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
const struct pll_rate *pll_rate = find_rate(rate);
return pll_rate->rate;
}
static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
struct hdmi *hdmi = phy_8960->hdmi;
const struct pll_rate *pll_rate = find_rate(rate);
int i;
DBG("rate=%lu", rate);
for (i = 0; pll_rate->conf[i].reg; i++)
hdmi_write(hdmi, pll_rate->conf[i].reg, pll_rate->conf[i].val);
phy_8960->pixclk = rate;
return 0;
}
static const struct clk_ops hdmi_pll_ops = {
.enable = hdmi_pll_enable,
.disable = hdmi_pll_disable,
.recalc_rate = hdmi_pll_recalc_rate,
.round_rate = hdmi_pll_round_rate,
.set_rate = hdmi_pll_set_rate,
};
static const char *hdmi_pll_parents[] = {
"pxo",
};
static struct clk_init_data pll_init = {
.name = "hdmi_pll",
.ops = &hdmi_pll_ops,
.parent_names = hdmi_pll_parents,
.num_parents = ARRAY_SIZE(hdmi_pll_parents),
};
#endif
/*
* HDMI Phy:
*/
static void hdmi_phy_8960_destroy(struct hdmi_phy *phy)
{
struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
kfree(phy_8960);
}
static void hdmi_phy_8960_reset(struct hdmi_phy *phy)
{
struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
struct hdmi *hdmi = phy_8960->hdmi;
unsigned int val;
val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET);
} else {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET);
}
if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
} else {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET_PLL);
}
msleep(100);
if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET);
} else {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET);
}
if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET_PLL);
} else {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
}
}
static void hdmi_phy_8960_powerup(struct hdmi_phy *phy,
unsigned long int pixclock)
{
struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
struct hdmi *hdmi = phy_8960->hdmi;
DBG("pixclock: %lu", pixclock);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG0, 0x1b);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG1, 0xf2);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG4, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG5, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG6, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG7, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG8, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG9, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG10, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG11, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG3, 0x20);
}
static void hdmi_phy_8960_powerdown(struct hdmi_phy *phy)
{
struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
struct hdmi *hdmi = phy_8960->hdmi;
DBG("");
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x7f);
}
static const struct hdmi_phy_funcs hdmi_phy_8960_funcs = {
.destroy = hdmi_phy_8960_destroy,
.reset = hdmi_phy_8960_reset,
.powerup = hdmi_phy_8960_powerup,
.powerdown = hdmi_phy_8960_powerdown,
};
struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
{
struct hdmi_phy_8960 *phy_8960;
struct hdmi_phy *phy = NULL;
int ret;
#ifdef CONFIG_COMMON_CLK
int i;
/* sanity check: */
for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)
if (WARN_ON(freqtbl[i].rate < freqtbl[i+1].rate))
return ERR_PTR(-EINVAL);
#endif
phy_8960 = kzalloc(sizeof(*phy_8960), GFP_KERNEL);
if (!phy_8960) {
ret = -ENOMEM;
goto fail;
}
phy = &phy_8960->base;
phy->funcs = &hdmi_phy_8960_funcs;
phy_8960->hdmi = hdmi;
#ifdef CONFIG_COMMON_CLK
phy_8960->pll_hw.init = &pll_init;
phy_8960->pll = devm_clk_register(hdmi->dev->dev, &phy_8960->pll_hw);
if (IS_ERR(phy_8960->pll)) {
ret = PTR_ERR(phy_8960->pll);
phy_8960->pll = NULL;
goto fail;
}
#endif
return phy;
fail:
if (phy)
hdmi_phy_8960_destroy(phy);
return ERR_PTR(ret);
}

View file

@ -0,0 +1,214 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "hdmi.h"
struct hdmi_phy_8x60 {
struct hdmi_phy base;
struct hdmi *hdmi;
};
#define to_hdmi_phy_8x60(x) container_of(x, struct hdmi_phy_8x60, base)
static void hdmi_phy_8x60_destroy(struct hdmi_phy *phy)
{
struct hdmi_phy_8x60 *phy_8x60 = to_hdmi_phy_8x60(phy);
kfree(phy_8x60);
}
static void hdmi_phy_8x60_reset(struct hdmi_phy *phy)
{
struct hdmi_phy_8x60 *phy_8x60 = to_hdmi_phy_8x60(phy);
struct hdmi *hdmi = phy_8x60->hdmi;
unsigned int val;
val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET);
} else {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET);
}
msleep(100);
if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET);
} else {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET);
}
}
static void hdmi_phy_8x60_powerup(struct hdmi_phy *phy,
unsigned long int pixclock)
{
struct hdmi_phy_8x60 *phy_8x60 = to_hdmi_phy_8x60(phy);
struct hdmi *hdmi = phy_8x60->hdmi;
/* De-serializer delay D/C for non-lbk mode: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG0,
HDMI_8x60_PHY_REG0_DESER_DEL_CTRL(3));
if (pixclock == 27000000) {
/* video_format == HDMI_VFRMT_720x480p60_16_9 */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG1,
HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(5) |
HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(3));
} else {
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG1,
HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(5) |
HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(4));
}
/* No matter what, start from the power down mode: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2,
HDMI_8x60_PHY_REG2_PD_PWRGEN |
HDMI_8x60_PHY_REG2_PD_PLL |
HDMI_8x60_PHY_REG2_PD_DRIVE_4 |
HDMI_8x60_PHY_REG2_PD_DRIVE_3 |
HDMI_8x60_PHY_REG2_PD_DRIVE_2 |
HDMI_8x60_PHY_REG2_PD_DRIVE_1 |
HDMI_8x60_PHY_REG2_PD_DESER);
/* Turn PowerGen on: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2,
HDMI_8x60_PHY_REG2_PD_PLL |
HDMI_8x60_PHY_REG2_PD_DRIVE_4 |
HDMI_8x60_PHY_REG2_PD_DRIVE_3 |
HDMI_8x60_PHY_REG2_PD_DRIVE_2 |
HDMI_8x60_PHY_REG2_PD_DRIVE_1 |
HDMI_8x60_PHY_REG2_PD_DESER);
/* Turn PLL power on: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2,
HDMI_8x60_PHY_REG2_PD_DRIVE_4 |
HDMI_8x60_PHY_REG2_PD_DRIVE_3 |
HDMI_8x60_PHY_REG2_PD_DRIVE_2 |
HDMI_8x60_PHY_REG2_PD_DRIVE_1 |
HDMI_8x60_PHY_REG2_PD_DESER);
/* Write to HIGH after PLL power down de-assert: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG3,
HDMI_8x60_PHY_REG3_PLL_ENABLE);
/* ASIC power on; PHY REG9 = 0 */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG9, 0);
/* Enable PLL lock detect, PLL lock det will go high after lock
* Enable the re-time logic
*/
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG12,
HDMI_8x60_PHY_REG12_RETIMING_EN |
HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN);
/* Drivers are on: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2,
HDMI_8x60_PHY_REG2_PD_DESER);
/* If the RX detector is needed: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2,
HDMI_8x60_PHY_REG2_RCV_SENSE_EN |
HDMI_8x60_PHY_REG2_PD_DESER);
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG4, 0);
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG5, 0);
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG6, 0);
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG7, 0);
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG8, 0);
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG9, 0);
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG10, 0);
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG11, 0);
/* If we want to use lock enable based on counting: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG12,
HDMI_8x60_PHY_REG12_RETIMING_EN |
HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN |
HDMI_8x60_PHY_REG12_FORCE_LOCK);
}
static void hdmi_phy_8x60_powerdown(struct hdmi_phy *phy)
{
struct hdmi_phy_8x60 *phy_8x60 = to_hdmi_phy_8x60(phy);
struct hdmi *hdmi = phy_8x60->hdmi;
/* Assert RESET PHY from controller */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
HDMI_PHY_CTRL_SW_RESET);
udelay(10);
/* De-assert RESET PHY from controller */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL, 0);
/* Turn off Driver */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2,
HDMI_8x60_PHY_REG2_PD_DRIVE_4 |
HDMI_8x60_PHY_REG2_PD_DRIVE_3 |
HDMI_8x60_PHY_REG2_PD_DRIVE_2 |
HDMI_8x60_PHY_REG2_PD_DRIVE_1 |
HDMI_8x60_PHY_REG2_PD_DESER);
udelay(10);
/* Disable PLL */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG3, 0);
/* Power down PHY, but keep RX-sense: */
hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2,
HDMI_8x60_PHY_REG2_RCV_SENSE_EN |
HDMI_8x60_PHY_REG2_PD_PWRGEN |
HDMI_8x60_PHY_REG2_PD_PLL |
HDMI_8x60_PHY_REG2_PD_DRIVE_4 |
HDMI_8x60_PHY_REG2_PD_DRIVE_3 |
HDMI_8x60_PHY_REG2_PD_DRIVE_2 |
HDMI_8x60_PHY_REG2_PD_DRIVE_1 |
HDMI_8x60_PHY_REG2_PD_DESER);
}
static const struct hdmi_phy_funcs hdmi_phy_8x60_funcs = {
.destroy = hdmi_phy_8x60_destroy,
.reset = hdmi_phy_8x60_reset,
.powerup = hdmi_phy_8x60_powerup,
.powerdown = hdmi_phy_8x60_powerdown,
};
struct hdmi_phy *hdmi_phy_8x60_init(struct hdmi *hdmi)
{
struct hdmi_phy_8x60 *phy_8x60;
struct hdmi_phy *phy = NULL;
int ret;
phy_8x60 = kzalloc(sizeof(*phy_8x60), GFP_KERNEL);
if (!phy_8x60) {
ret = -ENOMEM;
goto fail;
}
phy = &phy_8x60->base;
phy->funcs = &hdmi_phy_8x60_funcs;
phy_8x60->hdmi = hdmi;
return phy;
fail:
if (phy)
hdmi_phy_8x60_destroy(phy);
return ERR_PTR(ret);
}

View file

@ -0,0 +1,157 @@
/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "hdmi.h"
struct hdmi_phy_8x74 {
struct hdmi_phy base;
struct hdmi *hdmi;
void __iomem *mmio;
};
#define to_hdmi_phy_8x74(x) container_of(x, struct hdmi_phy_8x74, base)
static void phy_write(struct hdmi_phy_8x74 *phy, u32 reg, u32 data)
{
msm_writel(data, phy->mmio + reg);
}
//static u32 phy_read(struct hdmi_phy_8x74 *phy, u32 reg)
//{
// return msm_readl(phy->mmio + reg);
//}
static void hdmi_phy_8x74_destroy(struct hdmi_phy *phy)
{
struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
kfree(phy_8x74);
}
static void hdmi_phy_8x74_reset(struct hdmi_phy *phy)
{
struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
struct hdmi *hdmi = phy_8x74->hdmi;
unsigned int val;
/* NOTE that HDMI_PHY_CTL is in core mmio, not phy mmio: */
val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET);
} else {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET);
}
if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
} else {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET_PLL);
}
msleep(100);
if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET);
} else {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET);
}
if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
/* pull high */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val | HDMI_PHY_CTRL_SW_RESET_PLL);
} else {
/* pull low */
hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
}
}
static void hdmi_phy_8x74_powerup(struct hdmi_phy *phy,
unsigned long int pixclock)
{
struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
phy_write(phy_8x74, REG_HDMI_8x74_ANA_CFG0, 0x1b);
phy_write(phy_8x74, REG_HDMI_8x74_ANA_CFG1, 0xf2);
phy_write(phy_8x74, REG_HDMI_8x74_BIST_CFG0, 0x0);
phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN0, 0x0);
phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN1, 0x0);
phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN2, 0x0);
phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN3, 0x0);
phy_write(phy_8x74, REG_HDMI_8x74_PD_CTRL1, 0x20);
}
static void hdmi_phy_8x74_powerdown(struct hdmi_phy *phy)
{
struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
phy_write(phy_8x74, REG_HDMI_8x74_PD_CTRL0, 0x7f);
}
static const struct hdmi_phy_funcs hdmi_phy_8x74_funcs = {
.destroy = hdmi_phy_8x74_destroy,
.reset = hdmi_phy_8x74_reset,
.powerup = hdmi_phy_8x74_powerup,
.powerdown = hdmi_phy_8x74_powerdown,
};
struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi)
{
struct hdmi_phy_8x74 *phy_8x74;
struct hdmi_phy *phy = NULL;
int ret;
phy_8x74 = kzalloc(sizeof(*phy_8x74), GFP_KERNEL);
if (!phy_8x74) {
ret = -ENOMEM;
goto fail;
}
phy = &phy_8x74->base;
phy->funcs = &hdmi_phy_8x74_funcs;
phy_8x74->hdmi = hdmi;
/* for 8x74, the phy mmio is mapped separately: */
phy_8x74->mmio = msm_ioremap(hdmi->pdev,
"phy_physical", "HDMI_8x74");
if (IS_ERR(phy_8x74->mmio)) {
ret = PTR_ERR(phy_8x74->mmio);
goto fail;
}
return phy;
fail:
if (phy)
hdmi_phy_8x74_destroy(phy);
return ERR_PTR(ret);
}

View file

@ -0,0 +1,52 @@
#ifndef QFPROM_XML
#define QFPROM_XML
/* Autogenerated file, DO NOT EDIT manually!
This file was generated by the rules-ng-ng headergen tool in this git repository:
http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20457 bytes, from 2014-08-01 12:22:48)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-07-17 15:34:33)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define REG_QFPROM_CONFIG_ROW0_LSB 0x00000238
#define QFPROM_CONFIG_ROW0_LSB_HDMI_DISABLE 0x00200000
#define QFPROM_CONFIG_ROW0_LSB_HDCP_DISABLE 0x00400000
#endif /* QFPROM_XML */