omapdrm changes for v4.14
* HDMI hot plug IRQ support (instead of polling) * Big driver cleanup from Laurent (no functional changes) * OMAP5 DSI support (only the pinmuxing was missing) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZlZ+SAAoJEPo9qoy8lh71x/8P/is/jIhTMCRi4kwH7pDN/eoG Ie60ES9eovlN0Ld3HlTQWIT2s3y5zTJGdp1S2C+gbAubrOftnc51wv92p/3HxWZL cnbnIPUvJIToF60l1+khy1V0AZdgIpaBgqLlqXx0DRhrAh9e6/fZYot5jjFDI1LW ARMPkFP9S4nwOYx1uENTb6C61FaE+Q/D+tdYqSsbKP18h235UiTeqP5DAMUy+vE4 NR0fKUppQZugp/Nz0teVqHgP10WJJ8Tp878Zurxtb7ecrfdx5+Rm6r8e+yQ6pNty ZkKQYxt+HEk8f1N6zWBrQFpREDNKRdFgeZpXmnfDG7qdt/DpE/SI/0Be7k/4hhdy 0LdjQHfvFeXHg3ZKiFqaGmSUc7GNv1ZTvTjHbpTyHn40Xfd8G5O4RHemEs9g92Mh Fw+sUxW0nD1FutZai0VHTZKXyRHvvdQYRdgeluPeVUXdXcyxMq5tr/MUbRYlpYhY FYTfyjEnarjZ/BHlokr/cT+odoCSdCorcNmjn56rRufMgavI/yh86fgZDzGMgSgp vPaAS77FSU/vldEw/nJCZcXqsNi1xHqkwR1kqH8embvxhooW7njxTszfuXiGJhMJ TkWUV36s1cWI83ajBqdj7uuLSfKvBZJUHsiqhd5UShk/JgiahrqN85K1fB5Fz8M3 AAXArAka4RktMeYyZVIs =7wKU -----END PGP SIGNATURE----- Merge tag 'omapdrm-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux into drm-next omapdrm changes for v4.14 * HDMI hot plug IRQ support (instead of polling) * Big driver cleanup from Laurent (no functional changes) * OMAP5 DSI support (only the pinmuxing was missing) * tag 'omapdrm-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux: (60 commits) drm/omap: Potential NULL deref in omap_crtc_duplicate_state() drm/omap: remove no-op cleanup code drm/omap: rename omapdrm device back drm: omapdrm: Remove omapdrm platform data ARM: OMAP2+: Don't register omapdss device for omapdrm ARM: OMAP2+: Remove unused omapdrm platform device drm: omapdrm: Remove the omapdss driver drm: omapdrm: Register omapdrm platform device in omapdss driver drm: omapdrm: hdmi: Don't allocate PHY features dynamically drm: omapdrm: hdmi: Configure the PHY from the HDMI core version drm: omapdrm: hdmi: Configure the PLL from the HDMI core version drm: omapdrm: hdmi: Pass HDMI core version as integer to HDMI audio drm: omapdrm: hdmi: Replace OMAP SoC model check with HDMI xmit version drm: omapdrm: hdmi: Rename functions and structures to use hdmi_ prefix drm/omap: add OMAP5 DSIPHY lane-enable support drm/omap: use regmap_update_bit() when muxing DSI pads drm: omapdrm: Remove dss_features.h drm: omapdrm: Move supported outputs feature to dss driver drm: omapdrm: Move DSS_FCK feature to dss driver drm: omapdrm: Move PCD, LINEWIDTH and DOWNSCALE features to dispc driver ...
This commit is contained in:
commit
8824c751eb
|
@ -8,7 +8,7 @@ ccflags-y := -I$(srctree)/$(src)/include \
|
|||
# Common support
|
||||
obj-y := id.o io.o control.o devices.o fb.o timer.o pm.o \
|
||||
common.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
|
||||
omap_device.o omap-headsmp.o sram.o drm.o
|
||||
omap_device.o omap-headsmp.o sram.o
|
||||
|
||||
hwmod-common = omap_hwmod.o omap_hwmod_reset.o \
|
||||
omap_hwmod_common_data.o
|
||||
|
|
|
@ -33,6 +33,7 @@ static void __init __maybe_unused omap_generic_init(void)
|
|||
pdata_quirks_init(omap_dt_match_table);
|
||||
|
||||
omapdss_init_of();
|
||||
omap_soc_device_init();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOC_OMAP2420
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
*/
|
||||
#define FRAMEDONE_IRQ_TIMEOUT 100
|
||||
|
||||
#if defined(CONFIG_FB_OMAP2)
|
||||
static struct platform_device omap_display_device = {
|
||||
.name = "omapdss",
|
||||
.id = -1,
|
||||
|
@ -163,6 +164,64 @@ static enum omapdss_version __init omap_display_get_version(void)
|
|||
return OMAPDSS_VER_UNKNOWN;
|
||||
}
|
||||
|
||||
static int __init omapdss_init_fbdev(void)
|
||||
{
|
||||
static struct omap_dss_board_info board_data = {
|
||||
.dsi_enable_pads = omap_dsi_enable_pads,
|
||||
.dsi_disable_pads = omap_dsi_disable_pads,
|
||||
.set_min_bus_tput = omap_dss_set_min_bus_tput,
|
||||
};
|
||||
struct device_node *node;
|
||||
|
||||
board_data.version = omap_display_get_version();
|
||||
if (board_data.version == OMAPDSS_VER_UNKNOWN) {
|
||||
pr_err("DSS not supported on this SoC\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
omap_display_device.dev.platform_data = &board_data;
|
||||
|
||||
r = platform_device_register(&omap_display_device);
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omapdss device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* create vrfb device */
|
||||
r = omap_init_vrfb();
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omapvrfb device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* create FB device */
|
||||
r = omap_init_fb();
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omapfb device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* create V4L2 display device */
|
||||
r = omap_init_vout();
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omap_vout device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* add DSI info for omap4 */
|
||||
node = of_find_node_by_name(NULL, "omap4_padconf_global");
|
||||
if (node)
|
||||
omap4_dsi_mux_syscon = syscon_node_to_regmap(node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int omapdss_init_fbdev(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_FB_OMAP2 */
|
||||
|
||||
static void dispc_disable_outputs(void)
|
||||
{
|
||||
u32 v, irq_mask = 0;
|
||||
|
@ -335,16 +394,9 @@ static struct device_node * __init omapdss_find_dss_of_node(void)
|
|||
int __init omapdss_init_of(void)
|
||||
{
|
||||
int r;
|
||||
enum omapdss_version ver;
|
||||
struct device_node *node;
|
||||
struct platform_device *pdev;
|
||||
|
||||
static struct omap_dss_board_info board_data = {
|
||||
.dsi_enable_pads = omap_dsi_enable_pads,
|
||||
.dsi_disable_pads = omap_dsi_disable_pads,
|
||||
.set_min_bus_tput = omap_dss_set_min_bus_tput,
|
||||
};
|
||||
|
||||
/* only create dss helper devices if dss is enabled in the .dts */
|
||||
|
||||
node = omapdss_find_dss_of_node();
|
||||
|
@ -354,13 +406,6 @@ int __init omapdss_init_of(void)
|
|||
if (!of_device_is_available(node))
|
||||
return 0;
|
||||
|
||||
ver = omap_display_get_version();
|
||||
|
||||
if (ver == OMAPDSS_VER_UNKNOWN) {
|
||||
pr_err("DSS not supported on this SoC\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pdev = of_find_device_by_node(node);
|
||||
|
||||
if (!pdev) {
|
||||
|
@ -374,48 +419,5 @@ int __init omapdss_init_of(void)
|
|||
return r;
|
||||
}
|
||||
|
||||
board_data.version = ver;
|
||||
|
||||
omap_display_device.dev.platform_data = &board_data;
|
||||
|
||||
r = platform_device_register(&omap_display_device);
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omapdss device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* create DRM device */
|
||||
r = omap_init_drm();
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omapdrm device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* create vrfb device */
|
||||
r = omap_init_vrfb();
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omapvrfb device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* create FB device */
|
||||
r = omap_init_fb();
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omapfb device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* create V4L2 display device */
|
||||
r = omap_init_vout();
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omap_vout device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* add DSI info for omap4 */
|
||||
node = of_find_node_by_name(NULL, "omap4_padconf_global");
|
||||
if (node)
|
||||
omap4_dsi_mux_syscon = syscon_node_to_regmap(node);
|
||||
|
||||
return 0;
|
||||
return omapdss_init_fbdev();
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ struct omap_dss_dispc_dev_attr {
|
|||
bool has_framedonetv_irq;
|
||||
};
|
||||
|
||||
int omap_init_drm(void);
|
||||
int omap_init_vrfb(void);
|
||||
int omap_init_fb(void);
|
||||
int omap_init_vout(void);
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* DRM/KMS device registration for TI OMAP platforms
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments
|
||||
* Author: Rob Clark <rob.clark@linaro.org>
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_data/omap_drm.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "display.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_OMAP)
|
||||
|
||||
static struct omap_drm_platform_data platform_data;
|
||||
|
||||
static struct platform_device omap_drm_device = {
|
||||
.dev = {
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &platform_data,
|
||||
},
|
||||
.name = "omapdrm",
|
||||
.id = 0,
|
||||
};
|
||||
|
||||
int __init omap_init_drm(void)
|
||||
{
|
||||
platform_data.omaprev = GET_OMAP_TYPE;
|
||||
|
||||
return platform_device_register(&omap_drm_device);
|
||||
|
||||
}
|
||||
#else
|
||||
int __init omap_init_drm(void) { return 0; }
|
||||
#endif
|
|
@ -428,7 +428,6 @@ static void __init __maybe_unused omap_hwmod_init_postsetup(void)
|
|||
static void __init __maybe_unused omap_common_late_init(void)
|
||||
{
|
||||
omap2_common_pm_late_init();
|
||||
omap_soc_device_init();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOC_OMAP2420
|
||||
|
|
|
@ -198,6 +198,9 @@ static int tvc_probe(struct platform_device *pdev)
|
|||
struct omap_dss_device *dssdev;
|
||||
int r;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
return -ENODEV;
|
||||
|
||||
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
|
||||
if (!ddata)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
|
@ -37,6 +38,10 @@ static const struct videomode hdmic_default_vm = {
|
|||
struct panel_drv_data {
|
||||
struct omap_dss_device dssdev;
|
||||
struct omap_dss_device *in;
|
||||
void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
|
||||
void *hpd_cb_data;
|
||||
bool hpd_enabled;
|
||||
struct mutex hpd_lock;
|
||||
|
||||
struct device *dev;
|
||||
|
||||
|
@ -167,6 +172,70 @@ static bool hdmic_detect(struct omap_dss_device *dssdev)
|
|||
return in->ops.hdmi->detect(in);
|
||||
}
|
||||
|
||||
static int hdmic_register_hpd_cb(struct omap_dss_device *dssdev,
|
||||
void (*cb)(void *cb_data,
|
||||
enum drm_connector_status status),
|
||||
void *cb_data)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
struct omap_dss_device *in = ddata->in;
|
||||
|
||||
if (gpio_is_valid(ddata->hpd_gpio)) {
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
ddata->hpd_cb = cb;
|
||||
ddata->hpd_cb_data = cb_data;
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
return 0;
|
||||
} else if (in->ops.hdmi->register_hpd_cb) {
|
||||
return in->ops.hdmi->register_hpd_cb(in, cb, cb_data);
|
||||
}
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static void hdmic_unregister_hpd_cb(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
struct omap_dss_device *in = ddata->in;
|
||||
|
||||
if (gpio_is_valid(ddata->hpd_gpio)) {
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
ddata->hpd_cb = NULL;
|
||||
ddata->hpd_cb_data = NULL;
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
} else if (in->ops.hdmi->unregister_hpd_cb) {
|
||||
in->ops.hdmi->unregister_hpd_cb(in);
|
||||
}
|
||||
}
|
||||
|
||||
static void hdmic_enable_hpd(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
struct omap_dss_device *in = ddata->in;
|
||||
|
||||
if (gpio_is_valid(ddata->hpd_gpio)) {
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
ddata->hpd_enabled = true;
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
} else if (in->ops.hdmi->enable_hpd) {
|
||||
in->ops.hdmi->enable_hpd(in);
|
||||
}
|
||||
}
|
||||
|
||||
static void hdmic_disable_hpd(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
struct omap_dss_device *in = ddata->in;
|
||||
|
||||
if (gpio_is_valid(ddata->hpd_gpio)) {
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
ddata->hpd_enabled = false;
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
} else if (in->ops.hdmi->disable_hpd) {
|
||||
in->ops.hdmi->disable_hpd(in);
|
||||
}
|
||||
}
|
||||
|
||||
static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
|
@ -197,10 +266,34 @@ static struct omap_dss_driver hdmic_driver = {
|
|||
|
||||
.read_edid = hdmic_read_edid,
|
||||
.detect = hdmic_detect,
|
||||
.register_hpd_cb = hdmic_register_hpd_cb,
|
||||
.unregister_hpd_cb = hdmic_unregister_hpd_cb,
|
||||
.enable_hpd = hdmic_enable_hpd,
|
||||
.disable_hpd = hdmic_disable_hpd,
|
||||
.set_hdmi_mode = hdmic_set_hdmi_mode,
|
||||
.set_hdmi_infoframe = hdmic_set_infoframe,
|
||||
};
|
||||
|
||||
static irqreturn_t hdmic_hpd_isr(int irq, void *data)
|
||||
{
|
||||
struct panel_drv_data *ddata = data;
|
||||
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
if (ddata->hpd_enabled && ddata->hpd_cb) {
|
||||
enum drm_connector_status status;
|
||||
|
||||
if (hdmic_detect(&ddata->dssdev))
|
||||
status = connector_status_connected;
|
||||
else
|
||||
status = connector_status_disconnected;
|
||||
|
||||
ddata->hpd_cb(ddata->hpd_cb_data, status);
|
||||
}
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int hdmic_probe_of(struct platform_device *pdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
|
||||
|
@ -246,11 +339,22 @@ static int hdmic_probe(struct platform_device *pdev)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
mutex_init(&ddata->hpd_lock);
|
||||
|
||||
if (gpio_is_valid(ddata->hpd_gpio)) {
|
||||
r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
|
||||
GPIOF_DIR_IN, "hdmi_hpd");
|
||||
if (r)
|
||||
goto err_reg;
|
||||
|
||||
r = devm_request_threaded_irq(&pdev->dev,
|
||||
gpio_to_irq(ddata->hpd_gpio),
|
||||
NULL, hdmic_hpd_isr,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
|
||||
IRQF_ONESHOT,
|
||||
"hdmic hpd", ddata);
|
||||
if (r)
|
||||
goto err_reg;
|
||||
}
|
||||
|
||||
ddata->vm = hdmic_default_vm;
|
||||
|
|
|
@ -15,12 +15,17 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "../dss/omapdss.h"
|
||||
|
||||
struct panel_drv_data {
|
||||
struct omap_dss_device dssdev;
|
||||
struct omap_dss_device *in;
|
||||
void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
|
||||
void *hpd_cb_data;
|
||||
bool hpd_enabled;
|
||||
struct mutex hpd_lock;
|
||||
|
||||
struct gpio_desc *ct_cp_hpd_gpio;
|
||||
struct gpio_desc *ls_oe_gpio;
|
||||
|
@ -162,6 +167,49 @@ static bool tpd_detect(struct omap_dss_device *dssdev)
|
|||
return gpiod_get_value_cansleep(ddata->hpd_gpio);
|
||||
}
|
||||
|
||||
static int tpd_register_hpd_cb(struct omap_dss_device *dssdev,
|
||||
void (*cb)(void *cb_data,
|
||||
enum drm_connector_status status),
|
||||
void *cb_data)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
ddata->hpd_cb = cb;
|
||||
ddata->hpd_cb_data = cb_data;
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tpd_unregister_hpd_cb(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
ddata->hpd_cb = NULL;
|
||||
ddata->hpd_cb_data = NULL;
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
}
|
||||
|
||||
static void tpd_enable_hpd(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
ddata->hpd_enabled = true;
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
}
|
||||
|
||||
static void tpd_disable_hpd(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
ddata->hpd_enabled = false;
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
}
|
||||
|
||||
static int tpd_set_infoframe(struct omap_dss_device *dssdev,
|
||||
const struct hdmi_avi_infoframe *avi)
|
||||
{
|
||||
|
@ -193,10 +241,34 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
|
|||
|
||||
.read_edid = tpd_read_edid,
|
||||
.detect = tpd_detect,
|
||||
.register_hpd_cb = tpd_register_hpd_cb,
|
||||
.unregister_hpd_cb = tpd_unregister_hpd_cb,
|
||||
.enable_hpd = tpd_enable_hpd,
|
||||
.disable_hpd = tpd_disable_hpd,
|
||||
.set_infoframe = tpd_set_infoframe,
|
||||
.set_hdmi_mode = tpd_set_hdmi_mode,
|
||||
};
|
||||
|
||||
static irqreturn_t tpd_hpd_isr(int irq, void *data)
|
||||
{
|
||||
struct panel_drv_data *ddata = data;
|
||||
|
||||
mutex_lock(&ddata->hpd_lock);
|
||||
if (ddata->hpd_enabled && ddata->hpd_cb) {
|
||||
enum drm_connector_status status;
|
||||
|
||||
if (tpd_detect(&ddata->dssdev))
|
||||
status = connector_status_connected;
|
||||
else
|
||||
status = connector_status_disconnected;
|
||||
|
||||
ddata->hpd_cb(ddata->hpd_cb_data, status);
|
||||
}
|
||||
mutex_unlock(&ddata->hpd_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int tpd_probe_of(struct platform_device *pdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
|
||||
|
@ -261,6 +333,15 @@ static int tpd_probe(struct platform_device *pdev)
|
|||
|
||||
ddata->hpd_gpio = gpio;
|
||||
|
||||
mutex_init(&ddata->hpd_lock);
|
||||
|
||||
r = devm_request_threaded_irq(&pdev->dev, gpiod_to_irq(ddata->hpd_gpio),
|
||||
NULL, tpd_hpd_isr,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"tpd12s015 hpd", ddata);
|
||||
if (r)
|
||||
goto err_gpio;
|
||||
|
||||
dssdev = &ddata->dssdev;
|
||||
dssdev->ops.hdmi = &tpd_hdmi_ops;
|
||||
dssdev->dev = &pdev->dev;
|
||||
|
|
|
@ -231,6 +231,9 @@ static int panel_dpi_probe(struct platform_device *pdev)
|
|||
struct omap_dss_device *dssdev;
|
||||
int r;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
return -ENODEV;
|
||||
|
||||
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
|
||||
if (ddata == NULL)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -554,7 +554,7 @@ static struct attribute *dsicm_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group dsicm_attr_group = {
|
||||
static const struct attribute_group dsicm_attr_group = {
|
||||
.attrs = dsicm_attrs,
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "../dss/omapdss.h"
|
||||
|
||||
static struct videomode lb035q02_vm = {
|
||||
static const struct videomode lb035q02_vm = {
|
||||
.hactive = 320,
|
||||
.vactive = 240,
|
||||
|
||||
|
|
|
@ -503,7 +503,7 @@ static struct attribute *bldev_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group bldev_attr_group = {
|
||||
static const struct attribute_group bldev_attr_group = {
|
||||
.attrs = bldev_attrs,
|
||||
};
|
||||
|
||||
|
@ -720,6 +720,9 @@ static int acx565akm_probe(struct spi_device *spi)
|
|||
|
||||
dev_dbg(&spi->dev, "%s\n", __func__);
|
||||
|
||||
if (!spi->dev.of_node)
|
||||
return -ENODEV;
|
||||
|
||||
spi->mode = SPI_MODE_3;
|
||||
|
||||
ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
|
||||
|
|
|
@ -40,7 +40,7 @@ struct panel_drv_data {
|
|||
struct spi_device *spi_dev;
|
||||
};
|
||||
|
||||
static struct videomode td028ttec1_panel_vm = {
|
||||
static const struct videomode td028ttec1_panel_vm = {
|
||||
.hactive = 480,
|
||||
.vactive = 640,
|
||||
.pixelclock = 22153000,
|
||||
|
|
|
@ -282,7 +282,7 @@ static struct attribute *tpo_td043_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group tpo_td043_attr_group = {
|
||||
static const struct attribute_group tpo_td043_attr_group = {
|
||||
.attrs = tpo_td043_attrs,
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ omapdss-base-y := base.o display.o dss-of.o output.o
|
|||
|
||||
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
|
||||
# Core DSS files
|
||||
omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o \
|
||||
omapdss-y := core.o dss.o dispc.o dispc_coefs.o \
|
||||
pll.o video-pll.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
|
||||
|
|
|
@ -24,182 +24,10 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "omapdss.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static struct {
|
||||
struct platform_device *pdev;
|
||||
} core;
|
||||
|
||||
enum omapdss_version omapdss_get_version(void)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
|
||||
return pdata->version;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_get_version);
|
||||
|
||||
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
|
||||
{
|
||||
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
|
||||
|
||||
if (!board_data->dsi_enable_pads)
|
||||
return -ENOENT;
|
||||
|
||||
return board_data->dsi_enable_pads(dsi_id, lane_mask);
|
||||
}
|
||||
|
||||
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
|
||||
{
|
||||
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
|
||||
|
||||
if (!board_data->dsi_disable_pads)
|
||||
return;
|
||||
|
||||
return board_data->dsi_disable_pads(dsi_id, lane_mask);
|
||||
}
|
||||
|
||||
int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
|
||||
|
||||
if (pdata->set_min_bus_tput)
|
||||
return pdata->set_min_bus_tput(dev, tput);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
|
||||
static int dss_debug_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
void (*func)(struct seq_file *) = s->private;
|
||||
func(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dss_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations dss_debug_fops = {
|
||||
.open = dss_debug_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static struct dentry *dss_debugfs_dir;
|
||||
|
||||
static int dss_initialize_debugfs(void)
|
||||
{
|
||||
dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
|
||||
if (IS_ERR(dss_debugfs_dir)) {
|
||||
int err = PTR_ERR(dss_debugfs_dir);
|
||||
dss_debugfs_dir = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
|
||||
&dss_debug_dump_clocks, &dss_debug_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dss_uninitialize_debugfs(void)
|
||||
{
|
||||
if (dss_debugfs_dir)
|
||||
debugfs_remove_recursive(dss_debugfs_dir);
|
||||
}
|
||||
|
||||
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
|
||||
write, &dss_debug_fops);
|
||||
|
||||
return PTR_ERR_OR_ZERO(d);
|
||||
}
|
||||
#else /* CONFIG_OMAP2_DSS_DEBUGFS */
|
||||
static inline int dss_initialize_debugfs(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void dss_uninitialize_debugfs(void)
|
||||
{
|
||||
}
|
||||
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
|
||||
|
||||
/* PLATFORM DEVICE */
|
||||
|
||||
static void dss_disable_all_devices(void)
|
||||
{
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
for_each_dss_dev(dssdev) {
|
||||
if (!dssdev->driver)
|
||||
continue;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
dssdev->driver->disable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init omap_dss_probe(struct platform_device *pdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
core.pdev = pdev;
|
||||
|
||||
dss_features_init(omapdss_get_version());
|
||||
|
||||
r = dss_initialize_debugfs();
|
||||
if (r)
|
||||
goto err_debugfs;
|
||||
|
||||
return 0;
|
||||
|
||||
err_debugfs:
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omap_dss_remove(struct platform_device *pdev)
|
||||
{
|
||||
dss_uninitialize_debugfs();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_dss_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
DSSDBG("shutdown\n");
|
||||
dss_disable_all_devices();
|
||||
}
|
||||
|
||||
static struct platform_driver omap_dss_driver = {
|
||||
.remove = omap_dss_remove,
|
||||
.shutdown = omap_dss_shutdown,
|
||||
.driver = {
|
||||
.name = "omapdss",
|
||||
},
|
||||
};
|
||||
|
||||
/* INIT */
|
||||
static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
|
||||
|
@ -236,21 +64,25 @@ static void (*dss_output_drv_unreg_funcs[])(void) = {
|
|||
dss_uninit_platform_driver,
|
||||
};
|
||||
|
||||
static struct platform_device *omap_drm_device;
|
||||
|
||||
static int __init omap_dss_init(void)
|
||||
{
|
||||
int r;
|
||||
int i;
|
||||
|
||||
r = platform_driver_probe(&omap_dss_driver, omap_dss_probe);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
|
||||
r = dss_output_drv_reg_funcs[i]();
|
||||
if (r)
|
||||
goto err_reg;
|
||||
}
|
||||
|
||||
omap_drm_device = platform_device_register_simple("omapdrm", 0, NULL, 0);
|
||||
if (IS_ERR(omap_drm_device)) {
|
||||
r = PTR_ERR(omap_drm_device);
|
||||
goto err_reg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_reg:
|
||||
|
@ -259,8 +91,6 @@ static int __init omap_dss_init(void)
|
|||
++i)
|
||||
dss_output_drv_unreg_funcs[i]();
|
||||
|
||||
platform_driver_unregister(&omap_dss_driver);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -268,10 +98,10 @@ static void __exit omap_dss_exit(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
platform_device_unregister(omap_drm_device);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i)
|
||||
dss_output_drv_unreg_funcs[i]();
|
||||
|
||||
platform_driver_unregister(&omap_dss_driver);
|
||||
}
|
||||
|
||||
module_init(omap_dss_init);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,13 +32,14 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include "omapdss.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
struct dpi_data {
|
||||
struct platform_device *pdev;
|
||||
enum dss_model dss_model;
|
||||
|
||||
struct regulator *vdds_dsi_reg;
|
||||
enum dss_clk_source clk_src;
|
||||
|
@ -99,25 +100,21 @@ static enum dss_clk_source dpi_get_clk_src_dra7xx(enum omap_channel channel)
|
|||
return DSS_CLK_SRC_FCK;
|
||||
}
|
||||
|
||||
static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel)
|
||||
static enum dss_clk_source dpi_get_clk_src(struct dpi_data *dpi)
|
||||
{
|
||||
enum omap_channel channel = dpi->output.dispc_channel;
|
||||
|
||||
/*
|
||||
* XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
|
||||
* would also be used for DISPC fclk. Meaning, when the DPI output is
|
||||
* disabled, DISPC clock will be disabled, and TV out will stop.
|
||||
*/
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
case OMAPDSS_VER_AM43xx:
|
||||
switch (dpi->dss_model) {
|
||||
case DSS_MODEL_OMAP2:
|
||||
case DSS_MODEL_OMAP3:
|
||||
return DSS_CLK_SRC_FCK;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
case DSS_MODEL_OMAP4:
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return DSS_CLK_SRC_PLL1_1;
|
||||
|
@ -127,7 +124,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel)
|
|||
return DSS_CLK_SRC_FCK;
|
||||
}
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
case DSS_MODEL_OMAP5:
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return DSS_CLK_SRC_PLL1_1;
|
||||
|
@ -138,7 +135,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel)
|
|||
return DSS_CLK_SRC_FCK;
|
||||
}
|
||||
|
||||
case OMAPDSS_VER_DRA7xx:
|
||||
case DSS_MODEL_DRA7:
|
||||
return dpi_get_clk_src_dra7xx(channel);
|
||||
|
||||
default:
|
||||
|
@ -213,7 +210,7 @@ static bool dpi_calc_pll_cb(int n, int m, unsigned long fint,
|
|||
ctx->pll_cinfo.clkdco = clkdco;
|
||||
|
||||
return dss_pll_hsdiv_calc_a(ctx->pll, clkdco,
|
||||
ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
|
||||
ctx->pck_min, dss_get_max_fck_rate(),
|
||||
dpi_calc_hsdiv_cb, ctx);
|
||||
}
|
||||
|
||||
|
@ -403,19 +400,13 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
|
||||
mutex_lock(&dpi->lock);
|
||||
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi->vdds_dsi_reg) {
|
||||
DSSERR("no VDSS_DSI regulator\n");
|
||||
r = -ENODEV;
|
||||
goto err_no_reg;
|
||||
}
|
||||
|
||||
if (!out->dispc_channel_connected) {
|
||||
DSSERR("failed to enable display: no output/manager\n");
|
||||
r = -ENODEV;
|
||||
goto err_no_out_mgr;
|
||||
}
|
||||
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
|
||||
if (dpi->vdds_dsi_reg) {
|
||||
r = regulator_enable(dpi->vdds_dsi_reg);
|
||||
if (r)
|
||||
goto err_reg_enable;
|
||||
|
@ -459,11 +450,10 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
err_src_sel:
|
||||
dispc_runtime_put();
|
||||
err_get_dispc:
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
|
||||
if (dpi->vdds_dsi_reg)
|
||||
regulator_disable(dpi->vdds_dsi_reg);
|
||||
err_reg_enable:
|
||||
err_no_out_mgr:
|
||||
err_no_reg:
|
||||
mutex_unlock(&dpi->lock);
|
||||
return r;
|
||||
}
|
||||
|
@ -484,7 +474,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
|
|||
|
||||
dispc_runtime_put();
|
||||
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
|
||||
if (dpi->vdds_dsi_reg)
|
||||
regulator_disable(dpi->vdds_dsi_reg);
|
||||
|
||||
mutex_unlock(&dpi->lock);
|
||||
|
@ -575,11 +565,21 @@ static int dpi_verify_pll(struct dss_pll *pll)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct soc_device_attribute dpi_soc_devices[] = {
|
||||
{ .family = "OMAP3[456]*" },
|
||||
{ .family = "[AD]M37*" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int dpi_init_regulator(struct dpi_data *dpi)
|
||||
{
|
||||
struct regulator *vdds_dsi;
|
||||
|
||||
if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
|
||||
/*
|
||||
* The DPI uses the DSI VDDS on OMAP34xx, OMAP35xx, OMAP36xx, AM37xx and
|
||||
* DM37xx only.
|
||||
*/
|
||||
if (!soc_device_match(dpi_soc_devices))
|
||||
return 0;
|
||||
|
||||
if (dpi->vdds_dsi_reg)
|
||||
|
@ -604,7 +604,7 @@ static void dpi_init_pll(struct dpi_data *dpi)
|
|||
if (dpi->pll)
|
||||
return;
|
||||
|
||||
dpi->clk_src = dpi_get_clk_src(dpi->output.dispc_channel);
|
||||
dpi->clk_src = dpi_get_clk_src(dpi);
|
||||
|
||||
pll = dss_pll_find_by_src(dpi->clk_src);
|
||||
if (!pll)
|
||||
|
@ -624,18 +624,14 @@ static void dpi_init_pll(struct dpi_data *dpi)
|
|||
* the channel in some more dynamic manner, or get the channel as a user
|
||||
* parameter.
|
||||
*/
|
||||
static enum omap_channel dpi_get_channel(int port_num)
|
||||
static enum omap_channel dpi_get_channel(struct dpi_data *dpi, int port_num)
|
||||
{
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
case OMAPDSS_VER_AM43xx:
|
||||
switch (dpi->dss_model) {
|
||||
case DSS_MODEL_OMAP2:
|
||||
case DSS_MODEL_OMAP3:
|
||||
return OMAP_DSS_CHANNEL_LCD;
|
||||
|
||||
case OMAPDSS_VER_DRA7xx:
|
||||
case DSS_MODEL_DRA7:
|
||||
switch (port_num) {
|
||||
case 2:
|
||||
return OMAP_DSS_CHANNEL_LCD3;
|
||||
|
@ -646,12 +642,10 @@ static enum omap_channel dpi_get_channel(int port_num)
|
|||
return OMAP_DSS_CHANNEL_LCD;
|
||||
}
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
case DSS_MODEL_OMAP4:
|
||||
return OMAP_DSS_CHANNEL_LCD2;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
case DSS_MODEL_OMAP5:
|
||||
return OMAP_DSS_CHANNEL_LCD3;
|
||||
|
||||
default:
|
||||
|
@ -716,10 +710,8 @@ static const struct omapdss_dpi_ops dpi_ops = {
|
|||
.get_timings = dpi_get_timings,
|
||||
};
|
||||
|
||||
static void dpi_init_output_port(struct platform_device *pdev,
|
||||
struct device_node *port)
|
||||
static void dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
|
||||
{
|
||||
struct dpi_data *dpi = port->data;
|
||||
struct omap_dss_device *out = &dpi->output;
|
||||
int r;
|
||||
u32 port_num;
|
||||
|
@ -741,10 +733,10 @@ static void dpi_init_output_port(struct platform_device *pdev,
|
|||
break;
|
||||
}
|
||||
|
||||
out->dev = &pdev->dev;
|
||||
out->dev = &dpi->pdev->dev;
|
||||
out->id = OMAP_DSS_OUTPUT_DPI;
|
||||
out->output_type = OMAP_DISPLAY_TYPE_DPI;
|
||||
out->dispc_channel = dpi_get_channel(port_num);
|
||||
out->dispc_channel = dpi_get_channel(dpi, port_num);
|
||||
out->port_num = port_num;
|
||||
out->ops.dpi = &dpi_ops;
|
||||
out->owner = THIS_MODULE;
|
||||
|
@ -760,7 +752,8 @@ static void dpi_uninit_output_port(struct device_node *port)
|
|||
omapdss_unregister_output(out);
|
||||
}
|
||||
|
||||
int dpi_init_port(struct platform_device *pdev, struct device_node *port)
|
||||
int dpi_init_port(struct platform_device *pdev, struct device_node *port,
|
||||
enum dss_model dss_model)
|
||||
{
|
||||
struct dpi_data *dpi;
|
||||
struct device_node *ep;
|
||||
|
@ -786,11 +779,12 @@ int dpi_init_port(struct platform_device *pdev, struct device_node *port)
|
|||
of_node_put(ep);
|
||||
|
||||
dpi->pdev = pdev;
|
||||
dpi->dss_model = dss_model;
|
||||
port->data = dpi;
|
||||
|
||||
mutex_init(&dpi->lock);
|
||||
|
||||
dpi_init_output_port(pdev, port);
|
||||
dpi_init_output_port(dpi, port);
|
||||
|
||||
dpi->port_initialized = true;
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#define DSS_SUBSYS_NAME "DSI"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
|
@ -42,12 +44,12 @@
|
|||
#include <linux/of_graph.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include "omapdss.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
#define DSI_CATCH_MISSING_TE
|
||||
|
||||
|
@ -228,6 +230,12 @@ static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
|
|||
#define DSI_MAX_NR_ISRS 2
|
||||
#define DSI_MAX_NR_LANES 5
|
||||
|
||||
enum dsi_model {
|
||||
DSI_MODEL_OMAP3,
|
||||
DSI_MODEL_OMAP4,
|
||||
DSI_MODEL_OMAP5,
|
||||
};
|
||||
|
||||
enum dsi_lane_function {
|
||||
DSI_LANE_UNUSED = 0,
|
||||
DSI_LANE_CLK,
|
||||
|
@ -299,12 +307,36 @@ struct dsi_lp_clock_info {
|
|||
u16 lp_clk_div;
|
||||
};
|
||||
|
||||
struct dsi_module_id_data {
|
||||
u32 address;
|
||||
int id;
|
||||
};
|
||||
|
||||
enum dsi_quirks {
|
||||
DSI_QUIRK_PLL_PWR_BUG = (1 << 0), /* DSI-PLL power command 0x3 is not working */
|
||||
DSI_QUIRK_DCS_CMD_CONFIG_VC = (1 << 1),
|
||||
DSI_QUIRK_VC_OCP_WIDTH = (1 << 2),
|
||||
DSI_QUIRK_REVERSE_TXCLKESC = (1 << 3),
|
||||
DSI_QUIRK_GNQ = (1 << 4),
|
||||
DSI_QUIRK_PHY_DCC = (1 << 5),
|
||||
};
|
||||
|
||||
struct dsi_of_data {
|
||||
enum dsi_model model;
|
||||
const struct dss_pll_hw *pll_hw;
|
||||
const struct dsi_module_id_data *modules;
|
||||
unsigned int max_fck_freq;
|
||||
unsigned int max_pll_lpdiv;
|
||||
enum dsi_quirks quirks;
|
||||
};
|
||||
|
||||
struct dsi_data {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *proto_base;
|
||||
void __iomem *phy_base;
|
||||
void __iomem *pll_base;
|
||||
|
||||
const struct dsi_of_data *data;
|
||||
int module_id;
|
||||
|
||||
int irq;
|
||||
|
@ -312,6 +344,7 @@ struct dsi_data {
|
|||
bool is_enabled;
|
||||
|
||||
struct clk *dss_clk;
|
||||
struct regmap *syscon;
|
||||
|
||||
struct dispc_clock_info user_dispc_cinfo;
|
||||
struct dss_pll_clock_info user_dsi_cinfo;
|
||||
|
@ -397,13 +430,6 @@ struct dsi_packet_sent_handler_data {
|
|||
struct completion *completion;
|
||||
};
|
||||
|
||||
struct dsi_module_id_data {
|
||||
u32 address;
|
||||
int id;
|
||||
};
|
||||
|
||||
static const struct of_device_id dsi_of_match[];
|
||||
|
||||
#ifdef DSI_PERF_MEASURE
|
||||
static bool dsi_perf;
|
||||
module_param(dsi_perf, bool, 0644);
|
||||
|
@ -1186,6 +1212,7 @@ static int dsi_regulator_init(struct platform_device *dsidev)
|
|||
|
||||
static void _dsi_print_reset_status(struct platform_device *dsidev)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
u32 l;
|
||||
int b0, b1, b2;
|
||||
|
||||
|
@ -1194,7 +1221,7 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
|
|||
* I/O. */
|
||||
l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
|
||||
|
||||
if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
|
||||
if (dsi->data->quirks & DSI_QUIRK_REVERSE_TXCLKESC) {
|
||||
b0 = 28;
|
||||
b1 = 27;
|
||||
b2 = 26;
|
||||
|
@ -1297,7 +1324,7 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
|
|||
unsigned long dsi_fclk;
|
||||
unsigned lp_clk_div;
|
||||
unsigned long lp_clk;
|
||||
unsigned lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
|
||||
unsigned lpdiv_max = dsi->data->max_pll_lpdiv;
|
||||
|
||||
|
||||
lp_clk_div = dsi->user_lp_cinfo.lp_clk_div;
|
||||
|
@ -1349,11 +1376,12 @@ enum dsi_pll_power_state {
|
|||
static int dsi_pll_power(struct platform_device *dsidev,
|
||||
enum dsi_pll_power_state state)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int t = 0;
|
||||
|
||||
/* DSI-PLL power command 0x3 is not working */
|
||||
if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) &&
|
||||
state == DSI_PLL_POWER_ON_DIV)
|
||||
if ((dsi->data->quirks & DSI_QUIRK_PLL_PWR_BUG) &&
|
||||
state == DSI_PLL_POWER_ON_DIV)
|
||||
state = DSI_PLL_POWER_ON_ALL;
|
||||
|
||||
/* PLL_PWR_CMD */
|
||||
|
@ -1373,11 +1401,12 @@ static int dsi_pll_power(struct platform_device *dsidev,
|
|||
}
|
||||
|
||||
|
||||
static void dsi_pll_calc_dsi_fck(struct dss_pll_clock_info *cinfo)
|
||||
static void dsi_pll_calc_dsi_fck(struct dsi_data *dsi,
|
||||
struct dss_pll_clock_info *cinfo)
|
||||
{
|
||||
unsigned long max_dsi_fck;
|
||||
|
||||
max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
|
||||
max_dsi_fck = dsi->data->max_fck_freq;
|
||||
|
||||
cinfo->mX[HSDIV_DSI] = DIV_ROUND_UP(cinfo->clkdco, max_dsi_fck);
|
||||
cinfo->clkout[HSDIV_DSI] = cinfo->clkdco / cinfo->mX[HSDIV_DSI];
|
||||
|
@ -1773,13 +1802,14 @@ static int dsi_cio_power(struct platform_device *dsidev,
|
|||
|
||||
static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int val;
|
||||
|
||||
/* line buffer on OMAP3 is 1024 x 24bits */
|
||||
/* XXX: for some reason using full buffer size causes
|
||||
* considerable TX slowdown with update sizes that fill the
|
||||
* whole buffer */
|
||||
if (!dss_has_feature(FEAT_DSI_GNQ))
|
||||
if (!(dsi->data->quirks & DSI_QUIRK_GNQ))
|
||||
return 1023 * 3;
|
||||
|
||||
val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */
|
||||
|
@ -1872,6 +1902,7 @@ static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
|
|||
|
||||
static void dsi_cio_timings(struct platform_device *dsidev)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
u32 r;
|
||||
u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
|
||||
u32 tlpx_half, tclk_trail, tclk_zero;
|
||||
|
@ -1934,7 +1965,7 @@ static void dsi_cio_timings(struct platform_device *dsidev)
|
|||
r = FLD_MOD(r, tclk_trail, 15, 8);
|
||||
r = FLD_MOD(r, tclk_zero, 7, 0);
|
||||
|
||||
if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
|
||||
if (dsi->data->quirks & DSI_QUIRK_PHY_DCC) {
|
||||
r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
|
||||
r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
|
||||
r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
|
||||
|
@ -2006,7 +2037,7 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
|
|||
static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
|
||||
const u8 *offsets;
|
||||
|
||||
if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
|
||||
if (dsi->data->quirks & DSI_QUIRK_REVERSE_TXCLKESC)
|
||||
offsets = offsets_old;
|
||||
else
|
||||
offsets = offsets_new;
|
||||
|
@ -2060,6 +2091,83 @@ static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
|
|||
return mask;
|
||||
}
|
||||
|
||||
/* OMAP4 CONTROL_DSIPHY */
|
||||
#define OMAP4_DSIPHY_SYSCON_OFFSET 0x78
|
||||
|
||||
#define OMAP4_DSI2_LANEENABLE_SHIFT 29
|
||||
#define OMAP4_DSI2_LANEENABLE_MASK (0x7 << 29)
|
||||
#define OMAP4_DSI1_LANEENABLE_SHIFT 24
|
||||
#define OMAP4_DSI1_LANEENABLE_MASK (0x1f << 24)
|
||||
#define OMAP4_DSI1_PIPD_SHIFT 19
|
||||
#define OMAP4_DSI1_PIPD_MASK (0x1f << 19)
|
||||
#define OMAP4_DSI2_PIPD_SHIFT 14
|
||||
#define OMAP4_DSI2_PIPD_MASK (0x1f << 14)
|
||||
|
||||
static int dsi_omap4_mux_pads(struct dsi_data *dsi, unsigned int lanes)
|
||||
{
|
||||
u32 enable_mask, enable_shift;
|
||||
u32 pipd_mask, pipd_shift;
|
||||
|
||||
if (dsi->module_id == 0) {
|
||||
enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
|
||||
enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
|
||||
pipd_mask = OMAP4_DSI1_PIPD_MASK;
|
||||
pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
|
||||
} else if (dsi->module_id == 1) {
|
||||
enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
|
||||
enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
|
||||
pipd_mask = OMAP4_DSI2_PIPD_MASK;
|
||||
pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return regmap_update_bits(dsi->syscon, OMAP4_DSIPHY_SYSCON_OFFSET,
|
||||
enable_mask | pipd_mask,
|
||||
(lanes << enable_shift) | (lanes << pipd_shift));
|
||||
}
|
||||
|
||||
/* OMAP5 CONTROL_DSIPHY */
|
||||
|
||||
#define OMAP5_DSIPHY_SYSCON_OFFSET 0x74
|
||||
|
||||
#define OMAP5_DSI1_LANEENABLE_SHIFT 24
|
||||
#define OMAP5_DSI2_LANEENABLE_SHIFT 19
|
||||
#define OMAP5_DSI_LANEENABLE_MASK 0x1f
|
||||
|
||||
static int dsi_omap5_mux_pads(struct dsi_data *dsi, unsigned int lanes)
|
||||
{
|
||||
u32 enable_shift;
|
||||
|
||||
if (dsi->module_id == 0)
|
||||
enable_shift = OMAP5_DSI1_LANEENABLE_SHIFT;
|
||||
else if (dsi->module_id == 1)
|
||||
enable_shift = OMAP5_DSI2_LANEENABLE_SHIFT;
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
return regmap_update_bits(dsi->syscon, OMAP5_DSIPHY_SYSCON_OFFSET,
|
||||
OMAP5_DSI_LANEENABLE_MASK << enable_shift,
|
||||
lanes << enable_shift);
|
||||
}
|
||||
|
||||
static int dsi_enable_pads(struct dsi_data *dsi, unsigned int lane_mask)
|
||||
{
|
||||
if (dsi->data->model == DSI_MODEL_OMAP4)
|
||||
return dsi_omap4_mux_pads(dsi, lane_mask);
|
||||
if (dsi->data->model == DSI_MODEL_OMAP5)
|
||||
return dsi_omap5_mux_pads(dsi, lane_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dsi_disable_pads(struct dsi_data *dsi)
|
||||
{
|
||||
if (dsi->data->model == DSI_MODEL_OMAP4)
|
||||
dsi_omap4_mux_pads(dsi, 0);
|
||||
else if (dsi->data->model == DSI_MODEL_OMAP5)
|
||||
dsi_omap5_mux_pads(dsi, 0);
|
||||
}
|
||||
|
||||
static int dsi_cio_init(struct platform_device *dsidev)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
|
@ -2068,7 +2176,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
|
|||
|
||||
DSSDBG("DSI CIO init starts");
|
||||
|
||||
r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
|
||||
r = dsi_enable_pads(dsi, dsi_get_lane_mask(dsidev));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -2178,7 +2286,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
|
|||
dsi_cio_disable_lane_override(dsidev);
|
||||
err_scp_clk_dom:
|
||||
dsi_disable_scp_clk(dsidev);
|
||||
dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
|
||||
dsi_disable_pads(dsi);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2191,7 +2299,7 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
|
|||
|
||||
dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
|
||||
dsi_disable_scp_clk(dsidev);
|
||||
dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
|
||||
dsi_disable_pads(dsi);
|
||||
}
|
||||
|
||||
static void dsi_config_tx_fifo(struct platform_device *dsidev,
|
||||
|
@ -2439,7 +2547,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
|
|||
r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
|
||||
r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
|
||||
r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
|
||||
if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
|
||||
if (dsi->data->quirks & DSI_QUIRK_VC_OCP_WIDTH)
|
||||
r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */
|
||||
|
||||
r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
|
||||
|
@ -2474,7 +2582,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
|
|||
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
|
||||
|
||||
/* DCS_CMD_ENABLE */
|
||||
if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
|
||||
if (dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC) {
|
||||
bool enable = source == DSI_VC_SOURCE_VP;
|
||||
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
|
||||
}
|
||||
|
@ -3607,7 +3715,7 @@ static int dsi_proto_config(struct platform_device *dsidev)
|
|||
r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
|
||||
r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
|
||||
r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
|
||||
if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
|
||||
if (!(dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC)) {
|
||||
r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
|
||||
/* DCS_CMD_CODE, 1=start, 0=continue */
|
||||
r = FLD_MOD(r, 0, 25, 25);
|
||||
|
@ -4450,6 +4558,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
|
|||
unsigned long clkdco, void *data)
|
||||
{
|
||||
struct dsi_clk_calc_ctx *ctx = data;
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
|
||||
|
||||
ctx->dsi_cinfo.n = n;
|
||||
ctx->dsi_cinfo.m = m;
|
||||
|
@ -4457,7 +4566,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
|
|||
ctx->dsi_cinfo.clkdco = clkdco;
|
||||
|
||||
return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min,
|
||||
dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
|
||||
dsi->data->max_fck_freq,
|
||||
dsi_cm_calc_hsdiv_cb, ctx);
|
||||
}
|
||||
|
||||
|
@ -4749,6 +4858,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
|
|||
unsigned long clkdco, void *data)
|
||||
{
|
||||
struct dsi_clk_calc_ctx *ctx = data;
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
|
||||
|
||||
ctx->dsi_cinfo.n = n;
|
||||
ctx->dsi_cinfo.m = m;
|
||||
|
@ -4756,7 +4866,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
|
|||
ctx->dsi_cinfo.clkdco = clkdco;
|
||||
|
||||
return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min,
|
||||
dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
|
||||
dsi->data->max_fck_freq,
|
||||
dsi_vm_calc_hsdiv_cb, ctx);
|
||||
}
|
||||
|
||||
|
@ -4827,7 +4937,7 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
|
|||
goto err;
|
||||
}
|
||||
|
||||
dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
|
||||
dsi_pll_calc_dsi_fck(dsi, &ctx.dsi_cinfo);
|
||||
|
||||
r = dsi_lp_clock_calc(ctx.dsi_cinfo.clkout[HSDIV_DSI],
|
||||
config->lp_clk_min, config->lp_clk_max, &dsi->user_lp_cinfo);
|
||||
|
@ -4857,24 +4967,14 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
|
|||
* the channel in some more dynamic manner, or get the channel as a user
|
||||
* parameter.
|
||||
*/
|
||||
static enum omap_channel dsi_get_channel(int module_id)
|
||||
static enum omap_channel dsi_get_channel(struct dsi_data *dsi)
|
||||
{
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
case OMAPDSS_VER_AM43xx:
|
||||
DSSWARN("DSI not supported\n");
|
||||
switch (dsi->data->model) {
|
||||
case DSI_MODEL_OMAP3:
|
||||
return OMAP_DSS_CHANNEL_LCD;
|
||||
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
return OMAP_DSS_CHANNEL_LCD;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
switch (module_id) {
|
||||
case DSI_MODEL_OMAP4:
|
||||
switch (dsi->module_id) {
|
||||
case 0:
|
||||
return OMAP_DSS_CHANNEL_LCD;
|
||||
case 1:
|
||||
|
@ -4884,8 +4984,8 @@ static enum omap_channel dsi_get_channel(int module_id)
|
|||
return OMAP_DSS_CHANNEL_LCD;
|
||||
}
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
switch (module_id) {
|
||||
case DSI_MODEL_OMAP5:
|
||||
switch (dsi->module_id) {
|
||||
case 0:
|
||||
return OMAP_DSS_CHANNEL_LCD;
|
||||
case 1:
|
||||
|
@ -5065,7 +5165,7 @@ static void dsi_init_output(struct platform_device *dsidev)
|
|||
|
||||
out->output_type = OMAP_DISPLAY_TYPE_DSI;
|
||||
out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
|
||||
out->dispc_channel = dsi_get_channel(dsi->module_id);
|
||||
out->dispc_channel = dsi_get_channel(dsi);
|
||||
out->ops.dsi = &dsi_ops;
|
||||
out->owner = THIS_MODULE;
|
||||
|
||||
|
@ -5240,29 +5340,7 @@ static int dsi_init_pll_data(struct platform_device *dsidev)
|
|||
pll->id = dsi->module_id == 0 ? DSS_PLL_DSI1 : DSS_PLL_DSI2;
|
||||
pll->clkin = clk;
|
||||
pll->base = dsi->pll_base;
|
||||
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
pll->hw = &dss_omap3_dsi_pll_hw;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
pll->hw = &dss_omap4_dsi_pll_hw;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
pll->hw = &dss_omap5_dsi_pll_hw;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pll->hw = dsi->data->pll_hw;
|
||||
pll->ops = &dsi_pll_ops;
|
||||
|
||||
r = dss_pll_register(pll);
|
||||
|
@ -5273,9 +5351,74 @@ static int dsi_init_pll_data(struct platform_device *dsidev)
|
|||
}
|
||||
|
||||
/* DSI1 HW IP initialisation */
|
||||
static const struct dsi_of_data dsi_of_data_omap34xx = {
|
||||
.model = DSI_MODEL_OMAP3,
|
||||
.pll_hw = &dss_omap3_dsi_pll_hw,
|
||||
.modules = (const struct dsi_module_id_data[]) {
|
||||
{ .address = 0x4804fc00, .id = 0, },
|
||||
{ },
|
||||
},
|
||||
.max_fck_freq = 173000000,
|
||||
.max_pll_lpdiv = (1 << 13) - 1,
|
||||
.quirks = DSI_QUIRK_REVERSE_TXCLKESC,
|
||||
};
|
||||
|
||||
static const struct dsi_of_data dsi_of_data_omap36xx = {
|
||||
.model = DSI_MODEL_OMAP3,
|
||||
.pll_hw = &dss_omap3_dsi_pll_hw,
|
||||
.modules = (const struct dsi_module_id_data[]) {
|
||||
{ .address = 0x4804fc00, .id = 0, },
|
||||
{ },
|
||||
},
|
||||
.max_fck_freq = 173000000,
|
||||
.max_pll_lpdiv = (1 << 13) - 1,
|
||||
.quirks = DSI_QUIRK_PLL_PWR_BUG,
|
||||
};
|
||||
|
||||
static const struct dsi_of_data dsi_of_data_omap4 = {
|
||||
.model = DSI_MODEL_OMAP4,
|
||||
.pll_hw = &dss_omap4_dsi_pll_hw,
|
||||
.modules = (const struct dsi_module_id_data[]) {
|
||||
{ .address = 0x58004000, .id = 0, },
|
||||
{ .address = 0x58005000, .id = 1, },
|
||||
{ },
|
||||
},
|
||||
.max_fck_freq = 170000000,
|
||||
.max_pll_lpdiv = (1 << 13) - 1,
|
||||
.quirks = DSI_QUIRK_DCS_CMD_CONFIG_VC | DSI_QUIRK_VC_OCP_WIDTH
|
||||
| DSI_QUIRK_GNQ,
|
||||
};
|
||||
|
||||
static const struct dsi_of_data dsi_of_data_omap5 = {
|
||||
.model = DSI_MODEL_OMAP5,
|
||||
.pll_hw = &dss_omap5_dsi_pll_hw,
|
||||
.modules = (const struct dsi_module_id_data[]) {
|
||||
{ .address = 0x58004000, .id = 0, },
|
||||
{ .address = 0x58009000, .id = 1, },
|
||||
{ },
|
||||
},
|
||||
.max_fck_freq = 209250000,
|
||||
.max_pll_lpdiv = (1 << 13) - 1,
|
||||
.quirks = DSI_QUIRK_DCS_CMD_CONFIG_VC | DSI_QUIRK_VC_OCP_WIDTH
|
||||
| DSI_QUIRK_GNQ | DSI_QUIRK_PHY_DCC,
|
||||
};
|
||||
|
||||
static const struct of_device_id dsi_of_match[] = {
|
||||
{ .compatible = "ti,omap3-dsi", .data = &dsi_of_data_omap36xx, },
|
||||
{ .compatible = "ti,omap4-dsi", .data = &dsi_of_data_omap4, },
|
||||
{ .compatible = "ti,omap5-dsi", .data = &dsi_of_data_omap5, },
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct soc_device_attribute dsi_soc_devices[] = {
|
||||
{ .machine = "OMAP3[45]*", .data = &dsi_of_data_omap34xx },
|
||||
{ .machine = "AM35*", .data = &dsi_of_data_omap34xx },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
static int dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
struct platform_device *dsidev = to_platform_device(dev);
|
||||
const struct soc_device_attribute *soc;
|
||||
const struct dsi_module_id_data *d;
|
||||
u32 rev;
|
||||
int r, i;
|
||||
|
@ -5339,7 +5482,13 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
|
|||
return r;
|
||||
}
|
||||
|
||||
d = of_match_node(dsi_of_match, dsidev->dev.of_node)->data;
|
||||
soc = soc_device_match(dsi_soc_devices);
|
||||
if (soc)
|
||||
dsi->data = soc->data;
|
||||
else
|
||||
dsi->data = of_match_node(dsi_of_match, dev->of_node)->data;
|
||||
|
||||
d = dsi->data->modules;
|
||||
while (d->address != 0 && d->address != dsi_mem->start)
|
||||
d++;
|
||||
|
||||
|
@ -5350,6 +5499,24 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
|
|||
|
||||
dsi->module_id = d->id;
|
||||
|
||||
if (dsi->data->model == DSI_MODEL_OMAP4 ||
|
||||
dsi->data->model == DSI_MODEL_OMAP5) {
|
||||
struct device_node *np;
|
||||
|
||||
/*
|
||||
* The OMAP4/5 display DT bindings don't reference the padconf
|
||||
* syscon. Our only option to retrieve it is to find it by name.
|
||||
*/
|
||||
np = of_find_node_by_name(NULL,
|
||||
dsi->data->model == DSI_MODEL_OMAP4 ?
|
||||
"omap4_padconf_global" : "omap5_padconf_global");
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
dsi->syscon = syscon_node_to_regmap(np);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
/* DSI VCs initialization */
|
||||
for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
|
||||
dsi->vc[i].source = DSI_VC_SOURCE_L4;
|
||||
|
@ -5375,7 +5542,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
|
|||
|
||||
/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
|
||||
* of data to 3 by default */
|
||||
if (dss_has_feature(FEAT_DSI_GNQ))
|
||||
if (dsi->data->quirks & DSI_QUIRK_GNQ)
|
||||
/* NB_DATA_LANES */
|
||||
dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
|
||||
else
|
||||
|
@ -5495,30 +5662,6 @@ static const struct dev_pm_ops dsi_pm_ops = {
|
|||
.runtime_resume = dsi_runtime_resume,
|
||||
};
|
||||
|
||||
static const struct dsi_module_id_data dsi_of_data_omap3[] = {
|
||||
{ .address = 0x4804fc00, .id = 0, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct dsi_module_id_data dsi_of_data_omap4[] = {
|
||||
{ .address = 0x58004000, .id = 0, },
|
||||
{ .address = 0x58005000, .id = 1, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct dsi_module_id_data dsi_of_data_omap5[] = {
|
||||
{ .address = 0x58004000, .id = 0, },
|
||||
{ .address = 0x58009000, .id = 1, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct of_device_id dsi_of_match[] = {
|
||||
{ .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, },
|
||||
{ .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, },
|
||||
{ .compatible = "ti,omap5-dsi", .data = dsi_of_data_omap5, },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver omap_dsihw_driver = {
|
||||
.probe = dsi_probe,
|
||||
.remove = dsi_remove,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#define DSS_SUBSYS_NAME "DSS"
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
|
@ -38,14 +39,15 @@
|
|||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include "omapdss.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
#define DSS_SZ_REGS SZ_512
|
||||
|
||||
|
@ -69,15 +71,24 @@ struct dss_reg {
|
|||
#define REG_FLD_MOD(idx, val, start, end) \
|
||||
dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
|
||||
|
||||
struct dss_ops {
|
||||
int (*dpi_select_source)(int port, enum omap_channel channel);
|
||||
int (*select_lcd_source)(enum omap_channel channel,
|
||||
enum dss_clk_source clk_src);
|
||||
};
|
||||
|
||||
struct dss_features {
|
||||
enum dss_model model;
|
||||
u8 fck_div_max;
|
||||
unsigned int fck_freq_max;
|
||||
u8 dss_fck_multiplier;
|
||||
const char *parent_clk_name;
|
||||
const enum omap_display_type *ports;
|
||||
int num_ports;
|
||||
int (*dpi_select_source)(int port, enum omap_channel channel);
|
||||
int (*select_lcd_source)(enum omap_channel channel,
|
||||
enum dss_clk_source clk_src);
|
||||
const enum omap_dss_output_id *outputs;
|
||||
const struct dss_ops *ops;
|
||||
struct dss_reg_field dispc_clk_switch;
|
||||
bool has_lcd_clk_src;
|
||||
};
|
||||
|
||||
static struct {
|
||||
|
@ -139,8 +150,7 @@ static void dss_save_context(void)
|
|||
|
||||
SR(CONTROL);
|
||||
|
||||
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
|
||||
OMAP_DISPLAY_TYPE_SDI) {
|
||||
if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
|
||||
SR(SDI_CONTROL);
|
||||
SR(PLL_CONTROL);
|
||||
}
|
||||
|
@ -159,8 +169,7 @@ static void dss_restore_context(void)
|
|||
|
||||
RR(CONTROL);
|
||||
|
||||
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
|
||||
OMAP_DISPLAY_TYPE_SDI) {
|
||||
if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
|
||||
RR(SDI_CONTROL);
|
||||
RR(PLL_CONTROL);
|
||||
}
|
||||
|
@ -390,8 +399,7 @@ static void dss_dump_regs(struct seq_file *s)
|
|||
DUMPREG(DSS_SYSSTATUS);
|
||||
DUMPREG(DSS_CONTROL);
|
||||
|
||||
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
|
||||
OMAP_DISPLAY_TYPE_SDI) {
|
||||
if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
|
||||
DUMPREG(DSS_SDI_CONTROL);
|
||||
DUMPREG(DSS_PLL_CONTROL);
|
||||
DUMPREG(DSS_SDI_STATUS);
|
||||
|
@ -419,14 +427,12 @@ static int dss_get_channel_index(enum omap_channel channel)
|
|||
static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
|
||||
{
|
||||
int b;
|
||||
u8 start, end;
|
||||
|
||||
/*
|
||||
* We always use PRCM clock as the DISPC func clock, except on DSS3,
|
||||
* where we don't have separate DISPC and LCD clock sources.
|
||||
*/
|
||||
if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) &&
|
||||
clk_src != DSS_CLK_SRC_FCK))
|
||||
if (WARN_ON(dss.feat->has_lcd_clk_src && clk_src != DSS_CLK_SRC_FCK))
|
||||
return;
|
||||
|
||||
switch (clk_src) {
|
||||
|
@ -444,9 +450,9 @@ static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
|
|||
return;
|
||||
}
|
||||
|
||||
dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
|
||||
|
||||
REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */
|
||||
REG_FLD_MOD(DSS_CONTROL, b, /* DISPC_CLK_SWITCH */
|
||||
dss.feat->dispc_clk_switch.start,
|
||||
dss.feat->dispc_clk_switch.end);
|
||||
|
||||
dss.dispc_clk_source = clk_src;
|
||||
}
|
||||
|
@ -570,13 +576,13 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
|
|||
int idx = dss_get_channel_index(channel);
|
||||
int r;
|
||||
|
||||
if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
|
||||
if (!dss.feat->has_lcd_clk_src) {
|
||||
dss_select_dispc_clk_source(clk_src);
|
||||
dss.lcd_clk_source[idx] = clk_src;
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss.feat->select_lcd_source(channel, clk_src);
|
||||
r = dss.feat->ops->select_lcd_source(channel, clk_src);
|
||||
if (r)
|
||||
return;
|
||||
|
||||
|
@ -595,7 +601,7 @@ enum dss_clk_source dss_get_dsi_clk_source(int dsi_module)
|
|||
|
||||
enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
|
||||
{
|
||||
if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
|
||||
if (dss.feat->has_lcd_clk_src) {
|
||||
int idx = dss_get_channel_index(channel);
|
||||
return dss.lcd_clk_source[idx];
|
||||
} else {
|
||||
|
@ -615,7 +621,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
|
|||
unsigned long prate;
|
||||
unsigned m;
|
||||
|
||||
fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
||||
fck_hw_max = dss.feat->fck_freq_max;
|
||||
|
||||
if (dss.parent_clk == NULL) {
|
||||
unsigned pckd;
|
||||
|
@ -673,6 +679,16 @@ unsigned long dss_get_dispc_clk_rate(void)
|
|||
return dss.dss_clk_rate;
|
||||
}
|
||||
|
||||
unsigned long dss_get_max_fck_rate(void)
|
||||
{
|
||||
return dss.feat->fck_freq_max;
|
||||
}
|
||||
|
||||
enum omap_dss_output_id dss_get_supported_outputs(enum omap_channel channel)
|
||||
{
|
||||
return dss.feat->outputs[channel];
|
||||
}
|
||||
|
||||
static int dss_setup_default_clock(void)
|
||||
{
|
||||
unsigned long max_dss_fck, prate;
|
||||
|
@ -680,7 +696,7 @@ static int dss_setup_default_clock(void)
|
|||
unsigned fck_div;
|
||||
int r;
|
||||
|
||||
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
||||
max_dss_fck = dss.feat->fck_freq_max;
|
||||
|
||||
if (dss.parent_clk == NULL) {
|
||||
fck = clk_round_rate(dss.dss_clk, max_dss_fck);
|
||||
|
@ -721,27 +737,29 @@ void dss_set_dac_pwrdn_bgz(bool enable)
|
|||
|
||||
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
|
||||
{
|
||||
enum omap_display_type dp;
|
||||
dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
|
||||
enum omap_dss_output_id outputs;
|
||||
|
||||
outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT];
|
||||
|
||||
/* Complain about invalid selections */
|
||||
WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
|
||||
WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
|
||||
WARN_ON((src == DSS_VENC_TV_CLK) && !(outputs & OMAP_DSS_OUTPUT_VENC));
|
||||
WARN_ON((src == DSS_HDMI_M_PCLK) && !(outputs & OMAP_DSS_OUTPUT_HDMI));
|
||||
|
||||
/* Select only if we have options */
|
||||
if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
|
||||
if ((outputs & OMAP_DSS_OUTPUT_VENC) &&
|
||||
(outputs & OMAP_DSS_OUTPUT_HDMI))
|
||||
REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
|
||||
}
|
||||
|
||||
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
|
||||
{
|
||||
enum omap_display_type displays;
|
||||
enum omap_dss_output_id outputs;
|
||||
|
||||
displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
|
||||
if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
|
||||
outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT];
|
||||
if ((outputs & OMAP_DSS_OUTPUT_HDMI) == 0)
|
||||
return DSS_VENC_TV_CLK;
|
||||
|
||||
if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
|
||||
if ((outputs & OMAP_DSS_OUTPUT_VENC) == 0)
|
||||
return DSS_HDMI_M_PCLK;
|
||||
|
||||
return REG_GET(DSS_CONTROL, 15, 15);
|
||||
|
@ -823,7 +841,7 @@ static int dss_dpi_select_source_dra7xx(int port, enum omap_channel channel)
|
|||
|
||||
int dss_dpi_select_source(int port, enum omap_channel channel)
|
||||
{
|
||||
return dss.feat->dpi_select_source(port, channel);
|
||||
return dss.feat->ops->dpi_select_source(port, channel);
|
||||
}
|
||||
|
||||
static int dss_get_clocks(void)
|
||||
|
@ -882,7 +900,7 @@ void dss_runtime_put(void)
|
|||
|
||||
/* DEBUGFS */
|
||||
#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
|
||||
void dss_debug_dump_clocks(struct seq_file *s)
|
||||
static void dss_debug_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
dss_dump_clocks(s);
|
||||
dispc_dump_clocks(s);
|
||||
|
@ -890,8 +908,88 @@ void dss_debug_dump_clocks(struct seq_file *s)
|
|||
dsi_dump_clocks(s);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dss_debug_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
void (*func)(struct seq_file *) = s->private;
|
||||
|
||||
func(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dss_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations dss_debug_fops = {
|
||||
.open = dss_debug_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static struct dentry *dss_debugfs_dir;
|
||||
|
||||
static int dss_initialize_debugfs(void)
|
||||
{
|
||||
dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
|
||||
if (IS_ERR(dss_debugfs_dir)) {
|
||||
int err = PTR_ERR(dss_debugfs_dir);
|
||||
|
||||
dss_debugfs_dir = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
|
||||
&dss_debug_dump_clocks, &dss_debug_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dss_uninitialize_debugfs(void)
|
||||
{
|
||||
if (dss_debugfs_dir)
|
||||
debugfs_remove_recursive(dss_debugfs_dir);
|
||||
}
|
||||
|
||||
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
|
||||
write, &dss_debug_fops);
|
||||
|
||||
return PTR_ERR_OR_ZERO(d);
|
||||
}
|
||||
#else /* CONFIG_OMAP2_DSS_DEBUGFS */
|
||||
static inline int dss_initialize_debugfs(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void dss_uninitialize_debugfs(void)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
|
||||
|
||||
static const struct dss_ops dss_ops_omap2_omap3 = {
|
||||
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
|
||||
};
|
||||
|
||||
static const struct dss_ops dss_ops_omap4 = {
|
||||
.dpi_select_source = &dss_dpi_select_source_omap4,
|
||||
.select_lcd_source = &dss_lcd_clk_mux_omap4,
|
||||
};
|
||||
|
||||
static const struct dss_ops dss_ops_omap5 = {
|
||||
.dpi_select_source = &dss_dpi_select_source_omap5,
|
||||
.select_lcd_source = &dss_lcd_clk_mux_omap5,
|
||||
};
|
||||
|
||||
static const struct dss_ops dss_ops_dra7 = {
|
||||
.dpi_select_source = &dss_dpi_select_source_dra7xx,
|
||||
.select_lcd_source = &dss_lcd_clk_mux_dra7,
|
||||
};
|
||||
|
||||
static const enum omap_display_type omap2plus_ports[] = {
|
||||
OMAP_DISPLAY_TYPE_DPI,
|
||||
|
@ -908,130 +1006,168 @@ static const enum omap_display_type dra7xx_ports[] = {
|
|||
OMAP_DISPLAY_TYPE_DPI,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI2,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_HDMI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD3 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI2,
|
||||
};
|
||||
|
||||
static const struct dss_features omap24xx_dss_feats = {
|
||||
.model = DSS_MODEL_OMAP2,
|
||||
/*
|
||||
* fck div max is really 16, but the divider range has gaps. The range
|
||||
* from 1 to 6 has no gaps, so let's use that as a max.
|
||||
*/
|
||||
.fck_div_max = 6,
|
||||
.fck_freq_max = 133000000,
|
||||
.dss_fck_multiplier = 2,
|
||||
.parent_clk_name = "core_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
|
||||
.ports = omap2plus_ports,
|
||||
.num_ports = ARRAY_SIZE(omap2plus_ports),
|
||||
.outputs = omap2_dss_supported_outputs,
|
||||
.ops = &dss_ops_omap2_omap3,
|
||||
.dispc_clk_switch = { 0, 0 },
|
||||
.has_lcd_clk_src = false,
|
||||
};
|
||||
|
||||
static const struct dss_features omap34xx_dss_feats = {
|
||||
.model = DSS_MODEL_OMAP3,
|
||||
.fck_div_max = 16,
|
||||
.fck_freq_max = 173000000,
|
||||
.dss_fck_multiplier = 2,
|
||||
.parent_clk_name = "dpll4_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
|
||||
.ports = omap34xx_ports,
|
||||
.outputs = omap3430_dss_supported_outputs,
|
||||
.num_ports = ARRAY_SIZE(omap34xx_ports),
|
||||
.ops = &dss_ops_omap2_omap3,
|
||||
.dispc_clk_switch = { 0, 0 },
|
||||
.has_lcd_clk_src = false,
|
||||
};
|
||||
|
||||
static const struct dss_features omap3630_dss_feats = {
|
||||
.model = DSS_MODEL_OMAP3,
|
||||
.fck_div_max = 32,
|
||||
.fck_freq_max = 173000000,
|
||||
.dss_fck_multiplier = 1,
|
||||
.parent_clk_name = "dpll4_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
|
||||
.ports = omap2plus_ports,
|
||||
.num_ports = ARRAY_SIZE(omap2plus_ports),
|
||||
.outputs = omap3630_dss_supported_outputs,
|
||||
.ops = &dss_ops_omap2_omap3,
|
||||
.dispc_clk_switch = { 0, 0 },
|
||||
.has_lcd_clk_src = false,
|
||||
};
|
||||
|
||||
static const struct dss_features omap44xx_dss_feats = {
|
||||
.model = DSS_MODEL_OMAP4,
|
||||
.fck_div_max = 32,
|
||||
.fck_freq_max = 186000000,
|
||||
.dss_fck_multiplier = 1,
|
||||
.parent_clk_name = "dpll_per_x2_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap4,
|
||||
.ports = omap2plus_ports,
|
||||
.num_ports = ARRAY_SIZE(omap2plus_ports),
|
||||
.select_lcd_source = &dss_lcd_clk_mux_omap4,
|
||||
.outputs = omap4_dss_supported_outputs,
|
||||
.ops = &dss_ops_omap4,
|
||||
.dispc_clk_switch = { 9, 8 },
|
||||
.has_lcd_clk_src = true,
|
||||
};
|
||||
|
||||
static const struct dss_features omap54xx_dss_feats = {
|
||||
.model = DSS_MODEL_OMAP5,
|
||||
.fck_div_max = 64,
|
||||
.fck_freq_max = 209250000,
|
||||
.dss_fck_multiplier = 1,
|
||||
.parent_clk_name = "dpll_per_x2_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap5,
|
||||
.ports = omap2plus_ports,
|
||||
.num_ports = ARRAY_SIZE(omap2plus_ports),
|
||||
.select_lcd_source = &dss_lcd_clk_mux_omap5,
|
||||
.outputs = omap5_dss_supported_outputs,
|
||||
.ops = &dss_ops_omap5,
|
||||
.dispc_clk_switch = { 9, 7 },
|
||||
.has_lcd_clk_src = true,
|
||||
};
|
||||
|
||||
static const struct dss_features am43xx_dss_feats = {
|
||||
.model = DSS_MODEL_OMAP3,
|
||||
.fck_div_max = 0,
|
||||
.fck_freq_max = 200000000,
|
||||
.dss_fck_multiplier = 0,
|
||||
.parent_clk_name = NULL,
|
||||
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
|
||||
.ports = omap2plus_ports,
|
||||
.num_ports = ARRAY_SIZE(omap2plus_ports),
|
||||
.outputs = am43xx_dss_supported_outputs,
|
||||
.ops = &dss_ops_omap2_omap3,
|
||||
.dispc_clk_switch = { 0, 0 },
|
||||
.has_lcd_clk_src = true,
|
||||
};
|
||||
|
||||
static const struct dss_features dra7xx_dss_feats = {
|
||||
.model = DSS_MODEL_DRA7,
|
||||
.fck_div_max = 64,
|
||||
.fck_freq_max = 209250000,
|
||||
.dss_fck_multiplier = 1,
|
||||
.parent_clk_name = "dpll_per_x2_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_dra7xx,
|
||||
.ports = dra7xx_ports,
|
||||
.num_ports = ARRAY_SIZE(dra7xx_ports),
|
||||
.select_lcd_source = &dss_lcd_clk_mux_dra7,
|
||||
.outputs = omap5_dss_supported_outputs,
|
||||
.ops = &dss_ops_dra7,
|
||||
.dispc_clk_switch = { 9, 7 },
|
||||
.has_lcd_clk_src = true,
|
||||
};
|
||||
|
||||
static int dss_init_features(struct platform_device *pdev)
|
||||
{
|
||||
const struct dss_features *src;
|
||||
struct dss_features *dst;
|
||||
|
||||
dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
|
||||
if (!dst) {
|
||||
dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
src = &omap24xx_dss_feats;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
src = &omap34xx_dss_feats;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
src = &omap3630_dss_feats;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
src = &omap44xx_dss_feats;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
src = &omap54xx_dss_feats;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_AM43xx:
|
||||
src = &am43xx_dss_feats;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_DRA7xx:
|
||||
src = &dra7xx_dss_feats;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
dss.feat = dst;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_init_ports(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *parent = pdev->dev.of_node;
|
||||
|
@ -1045,7 +1181,7 @@ static int dss_init_ports(struct platform_device *pdev)
|
|||
|
||||
switch (dss.feat->ports[i]) {
|
||||
case OMAP_DISPLAY_TYPE_DPI:
|
||||
dpi_init_port(pdev, port);
|
||||
dpi_init_port(pdev, port, dss.feat->model);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_SDI:
|
||||
sdi_init_port(pdev, port);
|
||||
|
@ -1144,6 +1280,23 @@ static int dss_video_pll_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* DSS HW IP initialisation */
|
||||
static const struct of_device_id dss_of_match[] = {
|
||||
{ .compatible = "ti,omap2-dss", .data = &omap24xx_dss_feats },
|
||||
{ .compatible = "ti,omap3-dss", .data = &omap3630_dss_feats },
|
||||
{ .compatible = "ti,omap4-dss", .data = &omap44xx_dss_feats },
|
||||
{ .compatible = "ti,omap5-dss", .data = &omap54xx_dss_feats },
|
||||
{ .compatible = "ti,dra7-dss", .data = &dra7xx_dss_feats },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dss_of_match);
|
||||
|
||||
static const struct soc_device_attribute dss_soc_devices[] = {
|
||||
{ .machine = "OMAP3430/3530", .data = &omap34xx_dss_feats },
|
||||
{ .machine = "AM35??", .data = &omap34xx_dss_feats },
|
||||
{ .family = "AM43xx", .data = &am43xx_dss_feats },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int dss_bind(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
@ -1151,12 +1304,6 @@ static int dss_bind(struct device *dev)
|
|||
u32 rev;
|
||||
int r;
|
||||
|
||||
dss.pdev = pdev;
|
||||
|
||||
r = dss_init_features(dss.pdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
|
||||
dss.base = devm_ioremap_resource(&pdev->dev, dss_mem);
|
||||
if (IS_ERR(dss.base))
|
||||
|
@ -1288,15 +1435,34 @@ static int dss_add_child_component(struct device *dev, void *data)
|
|||
|
||||
static int dss_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct soc_device_attribute *soc;
|
||||
struct component_match *match = NULL;
|
||||
int r;
|
||||
|
||||
dss.pdev = pdev;
|
||||
|
||||
/*
|
||||
* The various OMAP3-based SoCs can't be told apart using the compatible
|
||||
* string, use SoC device matching.
|
||||
*/
|
||||
soc = soc_device_match(dss_soc_devices);
|
||||
if (soc)
|
||||
dss.feat = soc->data;
|
||||
else
|
||||
dss.feat = of_match_device(dss_of_match, &pdev->dev)->data;
|
||||
|
||||
r = dss_initialize_debugfs();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* add all the child devices as components */
|
||||
device_for_each_child(&pdev->dev, &match, dss_add_child_component);
|
||||
|
||||
r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
|
||||
if (r)
|
||||
if (r) {
|
||||
dss_uninitialize_debugfs();
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1304,9 +1470,27 @@ static int dss_probe(struct platform_device *pdev)
|
|||
static int dss_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_master_del(&pdev->dev, &dss_component_ops);
|
||||
|
||||
dss_uninitialize_debugfs();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dss_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
DSSDBG("shutdown\n");
|
||||
|
||||
for_each_dss_dev(dssdev) {
|
||||
if (!dssdev->driver)
|
||||
continue;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
dssdev->driver->disable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int dss_runtime_suspend(struct device *dev)
|
||||
{
|
||||
dss_save_context();
|
||||
|
@ -1343,20 +1527,10 @@ static const struct dev_pm_ops dss_pm_ops = {
|
|||
.runtime_resume = dss_runtime_resume,
|
||||
};
|
||||
|
||||
static const struct of_device_id dss_of_match[] = {
|
||||
{ .compatible = "ti,omap2-dss", },
|
||||
{ .compatible = "ti,omap3-dss", },
|
||||
{ .compatible = "ti,omap4-dss", },
|
||||
{ .compatible = "ti,omap5-dss", },
|
||||
{ .compatible = "ti,dra7-dss", },
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, dss_of_match);
|
||||
|
||||
static struct platform_driver omap_dsshw_driver = {
|
||||
.probe = dss_probe,
|
||||
.remove = dss_remove,
|
||||
.shutdown = dss_shutdown,
|
||||
.driver = {
|
||||
.name = "omapdss_dss",
|
||||
.pm = &dss_pm_ops,
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
#include "omapdss.h"
|
||||
|
||||
#define MAX_DSS_LCD_MANAGERS 3
|
||||
#define MAX_NUM_DSI 2
|
||||
|
||||
#ifdef pr_fmt
|
||||
#undef pr_fmt
|
||||
#endif
|
||||
|
@ -72,6 +75,14 @@
|
|||
#define FLD_MOD(orig, val, start, end) \
|
||||
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
|
||||
|
||||
enum dss_model {
|
||||
DSS_MODEL_OMAP2,
|
||||
DSS_MODEL_OMAP3,
|
||||
DSS_MODEL_OMAP4,
|
||||
DSS_MODEL_OMAP5,
|
||||
DSS_MODEL_DRA7,
|
||||
};
|
||||
|
||||
enum dss_io_pad_mode {
|
||||
DSS_IO_PAD_MODE_RESET,
|
||||
DSS_IO_PAD_MODE_RFBI,
|
||||
|
@ -192,6 +203,11 @@ struct dss_pll {
|
|||
struct dss_pll_clock_info cinfo;
|
||||
};
|
||||
|
||||
/* Defines a generic omap register field */
|
||||
struct dss_reg_field {
|
||||
u8 start, end;
|
||||
};
|
||||
|
||||
struct dispc_clock_info {
|
||||
/* rates that we get with dividers below */
|
||||
unsigned long lck;
|
||||
|
@ -219,10 +235,11 @@ struct seq_file;
|
|||
struct platform_device;
|
||||
|
||||
/* core */
|
||||
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
|
||||
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
|
||||
int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
|
||||
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
|
||||
static inline int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
|
||||
{
|
||||
/* To be implemented when the OMAP platform will provide this feature */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool dss_mgr_is_lcd(enum omap_channel id)
|
||||
{
|
||||
|
@ -234,6 +251,16 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)
|
|||
}
|
||||
|
||||
/* DSS */
|
||||
#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
|
||||
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
|
||||
#else
|
||||
static inline int dss_debugfs_create_file(const char *name,
|
||||
void (*write)(struct seq_file *))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
|
||||
|
||||
int dss_init_platform_driver(void) __init;
|
||||
void dss_uninit_platform_driver(void);
|
||||
|
||||
|
@ -241,6 +268,8 @@ int dss_runtime_get(void);
|
|||
void dss_runtime_put(void);
|
||||
|
||||
unsigned long dss_get_dispc_clk_rate(void);
|
||||
unsigned long dss_get_max_fck_rate(void);
|
||||
enum omap_dss_output_id dss_get_supported_outputs(enum omap_channel channel);
|
||||
int dss_dpi_select_source(int port, enum omap_channel channel);
|
||||
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
|
||||
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
|
||||
|
@ -252,10 +281,6 @@ struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id,
|
|||
struct regulator *regulator);
|
||||
void dss_video_pll_uninit(struct dss_pll *pll);
|
||||
|
||||
#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
|
||||
void dss_debug_dump_clocks(struct seq_file *s);
|
||||
#endif
|
||||
|
||||
void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable);
|
||||
|
||||
void dss_sdi_init(int datapairs);
|
||||
|
@ -312,11 +337,12 @@ void dsi_irq_handler(void);
|
|||
|
||||
/* DPI */
|
||||
#ifdef CONFIG_OMAP2_DSS_DPI
|
||||
int dpi_init_port(struct platform_device *pdev, struct device_node *port);
|
||||
int dpi_init_port(struct platform_device *pdev, struct device_node *port,
|
||||
enum dss_model dss_model);
|
||||
void dpi_uninit_port(struct device_node *port);
|
||||
#else
|
||||
static inline int dpi_init_port(struct platform_device *pdev,
|
||||
struct device_node *port)
|
||||
struct device_node *port, enum dss_model dss_model)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,905 +0,0 @@
|
|||
/*
|
||||
* linux/drivers/video/omap2/dss/dss_features.c
|
||||
*
|
||||
* Copyright (C) 2010 Texas Instruments
|
||||
* Author: Archit Taneja <archit@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
#include "omapdss.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
/* Defines a generic omap register field */
|
||||
struct dss_reg_field {
|
||||
u8 start, end;
|
||||
};
|
||||
|
||||
struct dss_param_range {
|
||||
int min, max;
|
||||
};
|
||||
|
||||
struct omap_dss_features {
|
||||
const struct dss_reg_field *reg_fields;
|
||||
const int num_reg_fields;
|
||||
|
||||
const enum dss_feat_id *features;
|
||||
const int num_features;
|
||||
|
||||
const int num_mgrs;
|
||||
const int num_ovls;
|
||||
const enum omap_display_type *supported_displays;
|
||||
const enum omap_dss_output_id *supported_outputs;
|
||||
const u32 **supported_color_modes;
|
||||
const enum omap_overlay_caps *overlay_caps;
|
||||
const struct dss_param_range *dss_params;
|
||||
|
||||
const u32 buffer_size_unit;
|
||||
const u32 burst_size_unit;
|
||||
};
|
||||
|
||||
/* This struct is assigned to one of the below during initialization */
|
||||
static const struct omap_dss_features *omap_current_dss_features;
|
||||
|
||||
static const struct dss_reg_field omap2_dss_reg_fields[] = {
|
||||
[FEAT_REG_FIRHINC] = { 11, 0 },
|
||||
[FEAT_REG_FIRVINC] = { 27, 16 },
|
||||
[FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 },
|
||||
[FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 },
|
||||
[FEAT_REG_FIFOSIZE] = { 8, 0 },
|
||||
[FEAT_REG_HORIZONTALACCU] = { 9, 0 },
|
||||
[FEAT_REG_VERTICALACCU] = { 25, 16 },
|
||||
[FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
|
||||
};
|
||||
|
||||
static const struct dss_reg_field omap3_dss_reg_fields[] = {
|
||||
[FEAT_REG_FIRHINC] = { 12, 0 },
|
||||
[FEAT_REG_FIRVINC] = { 28, 16 },
|
||||
[FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 },
|
||||
[FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 },
|
||||
[FEAT_REG_FIFOSIZE] = { 10, 0 },
|
||||
[FEAT_REG_HORIZONTALACCU] = { 9, 0 },
|
||||
[FEAT_REG_VERTICALACCU] = { 25, 16 },
|
||||
[FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
|
||||
};
|
||||
|
||||
static const struct dss_reg_field am43xx_dss_reg_fields[] = {
|
||||
[FEAT_REG_FIRHINC] = { 12, 0 },
|
||||
[FEAT_REG_FIRVINC] = { 28, 16 },
|
||||
[FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 },
|
||||
[FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 },
|
||||
[FEAT_REG_FIFOSIZE] = { 10, 0 },
|
||||
[FEAT_REG_HORIZONTALACCU] = { 9, 0 },
|
||||
[FEAT_REG_VERTICALACCU] = { 25, 16 },
|
||||
[FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
|
||||
};
|
||||
|
||||
static const struct dss_reg_field omap4_dss_reg_fields[] = {
|
||||
[FEAT_REG_FIRHINC] = { 12, 0 },
|
||||
[FEAT_REG_FIRVINC] = { 28, 16 },
|
||||
[FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
|
||||
[FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
|
||||
[FEAT_REG_FIFOSIZE] = { 15, 0 },
|
||||
[FEAT_REG_HORIZONTALACCU] = { 10, 0 },
|
||||
[FEAT_REG_VERTICALACCU] = { 26, 16 },
|
||||
[FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 },
|
||||
};
|
||||
|
||||
static const struct dss_reg_field omap5_dss_reg_fields[] = {
|
||||
[FEAT_REG_FIRHINC] = { 12, 0 },
|
||||
[FEAT_REG_FIRVINC] = { 28, 16 },
|
||||
[FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
|
||||
[FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
|
||||
[FEAT_REG_FIFOSIZE] = { 15, 0 },
|
||||
[FEAT_REG_HORIZONTALACCU] = { 10, 0 },
|
||||
[FEAT_REG_VERTICALACCU] = { 26, 16 },
|
||||
[FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 },
|
||||
};
|
||||
|
||||
static const enum omap_display_type omap2_dss_supported_displays[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DISPLAY_TYPE_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_display_type omap3430_dss_supported_displays[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
|
||||
OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DISPLAY_TYPE_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_display_type omap3630_dss_supported_displays[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
|
||||
OMAP_DISPLAY_TYPE_DSI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DISPLAY_TYPE_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_display_type am43xx_dss_supported_displays[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
|
||||
};
|
||||
|
||||
static const enum omap_display_type omap4_dss_supported_displays[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
|
||||
OMAP_DISPLAY_TYPE_DSI,
|
||||
};
|
||||
|
||||
static const enum omap_display_type omap5_dss_supported_displays[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
|
||||
OMAP_DISPLAY_TYPE_DSI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
|
||||
OMAP_DISPLAY_TYPE_DSI,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI2,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_HDMI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD3 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI2,
|
||||
};
|
||||
|
||||
#define COLOR_ARRAY(arr...) (const u32[]) { arr, 0 }
|
||||
|
||||
static const u32 *omap2_dss_supported_color_modes[] = {
|
||||
|
||||
/* OMAP_DSS_GFX */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGBX4444, DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888),
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_YUYV,
|
||||
DRM_FORMAT_UYVY),
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_YUYV,
|
||||
DRM_FORMAT_UYVY),
|
||||
};
|
||||
|
||||
static const u32 *omap3_dss_supported_color_modes[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444,
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888),
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888,
|
||||
DRM_FORMAT_RGBX4444, DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_YUYV, DRM_FORMAT_UYVY),
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444,
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_YUYV,
|
||||
DRM_FORMAT_UYVY, DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888),
|
||||
};
|
||||
|
||||
static const u32 *omap4_dss_supported_color_modes[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444,
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888,
|
||||
DRM_FORMAT_ARGB1555, DRM_FORMAT_XRGB4444,
|
||||
DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB1555),
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444,
|
||||
DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12,
|
||||
DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_UYVY,
|
||||
DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555,
|
||||
DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444,
|
||||
DRM_FORMAT_RGBX8888),
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444,
|
||||
DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12,
|
||||
DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_UYVY,
|
||||
DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555,
|
||||
DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444,
|
||||
DRM_FORMAT_RGBX8888),
|
||||
|
||||
/* OMAP_DSS_VIDEO3 */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444,
|
||||
DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12,
|
||||
DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_UYVY,
|
||||
DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555,
|
||||
DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444,
|
||||
DRM_FORMAT_RGBX8888),
|
||||
|
||||
/* OMAP_DSS_WB */
|
||||
COLOR_ARRAY(
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444,
|
||||
DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12,
|
||||
DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB888, DRM_FORMAT_UYVY,
|
||||
DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555,
|
||||
DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444,
|
||||
DRM_FORMAT_RGBX8888),
|
||||
};
|
||||
|
||||
static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
};
|
||||
|
||||
static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
};
|
||||
|
||||
static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
};
|
||||
|
||||
static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO3 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap2_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 133000000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 2, 255 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 2 },
|
||||
/*
|
||||
* Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
|
||||
* scaler cannot scale a image with width more than 768.
|
||||
*/
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 768 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap3_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range am43xx_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 200000000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap4_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap5_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 209250000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 209250000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap2_dss_feat_list[] = {
|
||||
FEAT_LCDENABLEPOL,
|
||||
FEAT_LCDENABLESIGNAL,
|
||||
FEAT_PCKFREEENABLE,
|
||||
FEAT_FUNCGATED,
|
||||
FEAT_ROWREPEATENABLE,
|
||||
FEAT_RESIZECONF,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap3430_dss_feat_list[] = {
|
||||
FEAT_LCDENABLEPOL,
|
||||
FEAT_LCDENABLESIGNAL,
|
||||
FEAT_PCKFREEENABLE,
|
||||
FEAT_FUNCGATED,
|
||||
FEAT_LINEBUFFERSPLIT,
|
||||
FEAT_ROWREPEATENABLE,
|
||||
FEAT_RESIZECONF,
|
||||
FEAT_DSI_REVERSE_TXCLKESC,
|
||||
FEAT_VENC_REQUIRES_TV_DAC_CLK,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FIXED_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_OMAP3_DSI_FIFO_BUG,
|
||||
FEAT_DPI_USES_VDDS_DSI,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id am35xx_dss_feat_list[] = {
|
||||
FEAT_LCDENABLEPOL,
|
||||
FEAT_LCDENABLESIGNAL,
|
||||
FEAT_PCKFREEENABLE,
|
||||
FEAT_FUNCGATED,
|
||||
FEAT_LINEBUFFERSPLIT,
|
||||
FEAT_ROWREPEATENABLE,
|
||||
FEAT_RESIZECONF,
|
||||
FEAT_DSI_REVERSE_TXCLKESC,
|
||||
FEAT_VENC_REQUIRES_TV_DAC_CLK,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FIXED_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_OMAP3_DSI_FIFO_BUG,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id am43xx_dss_feat_list[] = {
|
||||
FEAT_LCDENABLEPOL,
|
||||
FEAT_LCDENABLESIGNAL,
|
||||
FEAT_PCKFREEENABLE,
|
||||
FEAT_FUNCGATED,
|
||||
FEAT_LINEBUFFERSPLIT,
|
||||
FEAT_ROWREPEATENABLE,
|
||||
FEAT_RESIZECONF,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FIXED_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap3630_dss_feat_list[] = {
|
||||
FEAT_LCDENABLEPOL,
|
||||
FEAT_LCDENABLESIGNAL,
|
||||
FEAT_PCKFREEENABLE,
|
||||
FEAT_FUNCGATED,
|
||||
FEAT_LINEBUFFERSPLIT,
|
||||
FEAT_ROWREPEATENABLE,
|
||||
FEAT_RESIZECONF,
|
||||
FEAT_DSI_PLL_PWR_BUG,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FIXED_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_OMAP3_DSI_FIFO_BUG,
|
||||
FEAT_DPI_USES_VDDS_DSI,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
|
||||
FEAT_MGR_LCD2,
|
||||
FEAT_CORE_CLK_DIV,
|
||||
FEAT_LCD_CLK_SRC,
|
||||
FEAT_DSI_DCS_CMD_CONFIG_VC,
|
||||
FEAT_DSI_VC_OCP_WIDTH,
|
||||
FEAT_DSI_GNQ,
|
||||
FEAT_HANDLE_UV_SEPARATE,
|
||||
FEAT_ATTR2,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_BURST_2D,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
|
||||
FEAT_MGR_LCD2,
|
||||
FEAT_CORE_CLK_DIV,
|
||||
FEAT_LCD_CLK_SRC,
|
||||
FEAT_DSI_DCS_CMD_CONFIG_VC,
|
||||
FEAT_DSI_VC_OCP_WIDTH,
|
||||
FEAT_DSI_GNQ,
|
||||
FEAT_HDMI_CTS_SWMODE,
|
||||
FEAT_HANDLE_UV_SEPARATE,
|
||||
FEAT_ATTR2,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_BURST_2D,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap4_dss_feat_list[] = {
|
||||
FEAT_MGR_LCD2,
|
||||
FEAT_CORE_CLK_DIV,
|
||||
FEAT_LCD_CLK_SRC,
|
||||
FEAT_DSI_DCS_CMD_CONFIG_VC,
|
||||
FEAT_DSI_VC_OCP_WIDTH,
|
||||
FEAT_DSI_GNQ,
|
||||
FEAT_HDMI_CTS_SWMODE,
|
||||
FEAT_HDMI_AUDIO_USE_MCLK,
|
||||
FEAT_HANDLE_UV_SEPARATE,
|
||||
FEAT_ATTR2,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_BURST_2D,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap5_dss_feat_list[] = {
|
||||
FEAT_MGR_LCD2,
|
||||
FEAT_MGR_LCD3,
|
||||
FEAT_CORE_CLK_DIV,
|
||||
FEAT_LCD_CLK_SRC,
|
||||
FEAT_DSI_DCS_CMD_CONFIG_VC,
|
||||
FEAT_DSI_VC_OCP_WIDTH,
|
||||
FEAT_DSI_GNQ,
|
||||
FEAT_HDMI_CTS_SWMODE,
|
||||
FEAT_HDMI_AUDIO_USE_MCLK,
|
||||
FEAT_HANDLE_UV_SEPARATE,
|
||||
FEAT_ATTR2,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_BURST_2D,
|
||||
FEAT_DSI_PHY_DCC,
|
||||
FEAT_MFLAG,
|
||||
};
|
||||
|
||||
/* OMAP2 DSS Features */
|
||||
static const struct omap_dss_features omap2_dss_features = {
|
||||
.reg_fields = omap2_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
|
||||
|
||||
.features = omap2_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(omap2_dss_feat_list),
|
||||
|
||||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = omap2_dss_supported_displays,
|
||||
.supported_outputs = omap2_dss_supported_outputs,
|
||||
.supported_color_modes = omap2_dss_supported_color_modes,
|
||||
.overlay_caps = omap2_dss_overlay_caps,
|
||||
.dss_params = omap2_dss_param_range,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
|
||||
/* OMAP3 DSS Features */
|
||||
static const struct omap_dss_features omap3430_dss_features = {
|
||||
.reg_fields = omap3_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
|
||||
|
||||
.features = omap3430_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(omap3430_dss_feat_list),
|
||||
|
||||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = omap3430_dss_supported_displays,
|
||||
.supported_outputs = omap3430_dss_supported_outputs,
|
||||
.supported_color_modes = omap3_dss_supported_color_modes,
|
||||
.overlay_caps = omap3430_dss_overlay_caps,
|
||||
.dss_params = omap3_dss_param_range,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
|
||||
/*
|
||||
* AM35xx DSS Features. This is basically OMAP3 DSS Features without the
|
||||
* vdds_dsi regulator.
|
||||
*/
|
||||
static const struct omap_dss_features am35xx_dss_features = {
|
||||
.reg_fields = omap3_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
|
||||
|
||||
.features = am35xx_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(am35xx_dss_feat_list),
|
||||
|
||||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = omap3430_dss_supported_displays,
|
||||
.supported_outputs = omap3430_dss_supported_outputs,
|
||||
.supported_color_modes = omap3_dss_supported_color_modes,
|
||||
.overlay_caps = omap3430_dss_overlay_caps,
|
||||
.dss_params = omap3_dss_param_range,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
|
||||
static const struct omap_dss_features am43xx_dss_features = {
|
||||
.reg_fields = am43xx_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(am43xx_dss_reg_fields),
|
||||
|
||||
.features = am43xx_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(am43xx_dss_feat_list),
|
||||
|
||||
.num_mgrs = 1,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = am43xx_dss_supported_displays,
|
||||
.supported_outputs = am43xx_dss_supported_outputs,
|
||||
.supported_color_modes = omap3_dss_supported_color_modes,
|
||||
.overlay_caps = omap3430_dss_overlay_caps,
|
||||
.dss_params = am43xx_dss_param_range,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
|
||||
static const struct omap_dss_features omap3630_dss_features = {
|
||||
.reg_fields = omap3_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
|
||||
|
||||
.features = omap3630_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(omap3630_dss_feat_list),
|
||||
|
||||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = omap3630_dss_supported_displays,
|
||||
.supported_outputs = omap3630_dss_supported_outputs,
|
||||
.supported_color_modes = omap3_dss_supported_color_modes,
|
||||
.overlay_caps = omap3630_dss_overlay_caps,
|
||||
.dss_params = omap3_dss_param_range,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
|
||||
/* OMAP4 DSS Features */
|
||||
/* For OMAP4430 ES 1.0 revision */
|
||||
static const struct omap_dss_features omap4430_es1_0_dss_features = {
|
||||
.reg_fields = omap4_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
|
||||
|
||||
.features = omap4430_es1_0_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list),
|
||||
|
||||
.num_mgrs = 3,
|
||||
.num_ovls = 4,
|
||||
.supported_displays = omap4_dss_supported_displays,
|
||||
.supported_outputs = omap4_dss_supported_outputs,
|
||||
.supported_color_modes = omap4_dss_supported_color_modes,
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.dss_params = omap4_dss_param_range,
|
||||
.buffer_size_unit = 16,
|
||||
.burst_size_unit = 16,
|
||||
};
|
||||
|
||||
/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */
|
||||
static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
|
||||
.reg_fields = omap4_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
|
||||
|
||||
.features = omap4430_es2_0_1_2_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list),
|
||||
|
||||
.num_mgrs = 3,
|
||||
.num_ovls = 4,
|
||||
.supported_displays = omap4_dss_supported_displays,
|
||||
.supported_outputs = omap4_dss_supported_outputs,
|
||||
.supported_color_modes = omap4_dss_supported_color_modes,
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.dss_params = omap4_dss_param_range,
|
||||
.buffer_size_unit = 16,
|
||||
.burst_size_unit = 16,
|
||||
};
|
||||
|
||||
/* For all the other OMAP4 versions */
|
||||
static const struct omap_dss_features omap4_dss_features = {
|
||||
.reg_fields = omap4_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
|
||||
|
||||
.features = omap4_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(omap4_dss_feat_list),
|
||||
|
||||
.num_mgrs = 3,
|
||||
.num_ovls = 4,
|
||||
.supported_displays = omap4_dss_supported_displays,
|
||||
.supported_outputs = omap4_dss_supported_outputs,
|
||||
.supported_color_modes = omap4_dss_supported_color_modes,
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.dss_params = omap4_dss_param_range,
|
||||
.buffer_size_unit = 16,
|
||||
.burst_size_unit = 16,
|
||||
};
|
||||
|
||||
/* OMAP5 DSS Features */
|
||||
static const struct omap_dss_features omap5_dss_features = {
|
||||
.reg_fields = omap5_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
|
||||
|
||||
.features = omap5_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(omap5_dss_feat_list),
|
||||
|
||||
.num_mgrs = 4,
|
||||
.num_ovls = 4,
|
||||
.supported_displays = omap5_dss_supported_displays,
|
||||
.supported_outputs = omap5_dss_supported_outputs,
|
||||
.supported_color_modes = omap4_dss_supported_color_modes,
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.dss_params = omap5_dss_param_range,
|
||||
.buffer_size_unit = 16,
|
||||
.burst_size_unit = 16,
|
||||
};
|
||||
|
||||
/* Functions returning values related to a DSS feature */
|
||||
int dss_feat_get_num_mgrs(void)
|
||||
{
|
||||
return omap_current_dss_features->num_mgrs;
|
||||
}
|
||||
|
||||
int dss_feat_get_num_ovls(void)
|
||||
{
|
||||
return omap_current_dss_features->num_ovls;
|
||||
}
|
||||
|
||||
unsigned long dss_feat_get_param_min(enum dss_range_param param)
|
||||
{
|
||||
return omap_current_dss_features->dss_params[param].min;
|
||||
}
|
||||
|
||||
unsigned long dss_feat_get_param_max(enum dss_range_param param)
|
||||
{
|
||||
return omap_current_dss_features->dss_params[param].max;
|
||||
}
|
||||
|
||||
enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
|
||||
{
|
||||
return omap_current_dss_features->supported_displays[channel];
|
||||
}
|
||||
|
||||
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
|
||||
{
|
||||
return omap_current_dss_features->supported_outputs[channel];
|
||||
}
|
||||
|
||||
const u32 *dss_feat_get_supported_color_modes(enum omap_plane_id plane)
|
||||
{
|
||||
return omap_current_dss_features->supported_color_modes[plane];
|
||||
}
|
||||
|
||||
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane_id plane)
|
||||
{
|
||||
return omap_current_dss_features->overlay_caps[plane];
|
||||
}
|
||||
|
||||
bool dss_feat_color_mode_supported(enum omap_plane_id plane, u32 fourcc)
|
||||
{
|
||||
const u32 *modes;
|
||||
unsigned int i;
|
||||
|
||||
modes = omap_current_dss_features->supported_color_modes[plane];
|
||||
|
||||
for (i = 0; modes[i]; ++i) {
|
||||
if (modes[i] == fourcc)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 dss_feat_get_buffer_size_unit(void)
|
||||
{
|
||||
return omap_current_dss_features->buffer_size_unit;
|
||||
}
|
||||
|
||||
u32 dss_feat_get_burst_size_unit(void)
|
||||
{
|
||||
return omap_current_dss_features->burst_size_unit;
|
||||
}
|
||||
|
||||
/* DSS has_feature check */
|
||||
bool dss_has_feature(enum dss_feat_id id)
|
||||
{
|
||||
int i;
|
||||
const enum dss_feat_id *features = omap_current_dss_features->features;
|
||||
const int num_features = omap_current_dss_features->num_features;
|
||||
|
||||
for (i = 0; i < num_features; i++) {
|
||||
if (features[i] == id)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
|
||||
{
|
||||
if (id >= omap_current_dss_features->num_reg_fields)
|
||||
BUG();
|
||||
|
||||
*start = omap_current_dss_features->reg_fields[id].start;
|
||||
*end = omap_current_dss_features->reg_fields[id].end;
|
||||
}
|
||||
|
||||
void dss_features_init(enum omapdss_version version)
|
||||
{
|
||||
switch (version) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
omap_current_dss_features = &omap2_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
omap_current_dss_features = &omap3430_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
omap_current_dss_features = &omap3630_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
omap_current_dss_features = &omap4430_es1_0_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
omap_current_dss_features = &omap4_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
case OMAPDSS_VER_DRA7xx:
|
||||
omap_current_dss_features = &omap5_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
omap_current_dss_features = &am35xx_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_AM43xx:
|
||||
omap_current_dss_features = &am43xx_dss_features;
|
||||
break;
|
||||
|
||||
default:
|
||||
DSSWARN("Unsupported OMAP version");
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* linux/drivers/video/omap2/dss/dss_features.h
|
||||
*
|
||||
* Copyright (C) 2010 Texas Instruments
|
||||
* Author: Archit Taneja <archit@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __OMAP2_DSS_FEATURES_H
|
||||
#define __OMAP2_DSS_FEATURES_H
|
||||
|
||||
#define MAX_DSS_MANAGERS 4
|
||||
#define MAX_DSS_OVERLAYS 4
|
||||
#define MAX_DSS_LCD_MANAGERS 3
|
||||
#define MAX_NUM_DSI 2
|
||||
|
||||
/* DSS has feature id */
|
||||
enum dss_feat_id {
|
||||
FEAT_LCDENABLEPOL,
|
||||
FEAT_LCDENABLESIGNAL,
|
||||
FEAT_PCKFREEENABLE,
|
||||
FEAT_FUNCGATED,
|
||||
FEAT_MGR_LCD2,
|
||||
FEAT_MGR_LCD3,
|
||||
FEAT_LINEBUFFERSPLIT,
|
||||
FEAT_ROWREPEATENABLE,
|
||||
FEAT_RESIZECONF,
|
||||
/* Independent core clk divider */
|
||||
FEAT_CORE_CLK_DIV,
|
||||
FEAT_LCD_CLK_SRC,
|
||||
/* DSI-PLL power command 0x3 is not working */
|
||||
FEAT_DSI_PLL_PWR_BUG,
|
||||
FEAT_DSI_DCS_CMD_CONFIG_VC,
|
||||
FEAT_DSI_VC_OCP_WIDTH,
|
||||
FEAT_DSI_REVERSE_TXCLKESC,
|
||||
FEAT_DSI_GNQ,
|
||||
FEAT_DPI_USES_VDDS_DSI,
|
||||
FEAT_HDMI_CTS_SWMODE,
|
||||
FEAT_HDMI_AUDIO_USE_MCLK,
|
||||
FEAT_HANDLE_UV_SEPARATE,
|
||||
FEAT_ATTR2,
|
||||
FEAT_VENC_REQUIRES_TV_DAC_CLK,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FIXED_ZORDER,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
/* An unknown HW bug causing the normal FIFO thresholds not to work */
|
||||
FEAT_OMAP3_DSI_FIFO_BUG,
|
||||
FEAT_BURST_2D,
|
||||
FEAT_DSI_PHY_DCC,
|
||||
FEAT_MFLAG,
|
||||
};
|
||||
|
||||
/* DSS register field id */
|
||||
enum dss_feat_reg_field {
|
||||
FEAT_REG_FIRHINC,
|
||||
FEAT_REG_FIRVINC,
|
||||
FEAT_REG_FIFOHIGHTHRESHOLD,
|
||||
FEAT_REG_FIFOLOWTHRESHOLD,
|
||||
FEAT_REG_FIFOSIZE,
|
||||
FEAT_REG_HORIZONTALACCU,
|
||||
FEAT_REG_VERTICALACCU,
|
||||
FEAT_REG_DISPC_CLK_SWITCH,
|
||||
};
|
||||
|
||||
enum dss_range_param {
|
||||
FEAT_PARAM_DSS_FCK,
|
||||
FEAT_PARAM_DSS_PCD,
|
||||
FEAT_PARAM_DSIPLL_LPDIV,
|
||||
FEAT_PARAM_DSI_FCK,
|
||||
FEAT_PARAM_DOWNSCALE,
|
||||
FEAT_PARAM_LINEWIDTH,
|
||||
};
|
||||
|
||||
/* DSS Feature Functions */
|
||||
unsigned long dss_feat_get_param_min(enum dss_range_param param);
|
||||
unsigned long dss_feat_get_param_max(enum dss_range_param param);
|
||||
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane_id plane);
|
||||
bool dss_feat_color_mode_supported(enum omap_plane_id plane,
|
||||
u32 fourcc);
|
||||
|
||||
u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
|
||||
u32 dss_feat_get_burst_size_unit(void); /* in bytes */
|
||||
|
||||
bool dss_has_feature(enum dss_feat_id id);
|
||||
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
|
||||
void dss_features_init(enum omapdss_version version);
|
||||
|
||||
enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
|
||||
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
|
||||
|
||||
int dss_feat_get_num_mgrs(void);
|
||||
int dss_feat_get_num_ovls(void);
|
||||
const u32 *dss_feat_get_supported_color_modes(enum omap_plane_id plane);
|
||||
|
||||
#endif
|
|
@ -234,6 +234,7 @@ struct hdmi_core_audio_config {
|
|||
struct hdmi_wp_data {
|
||||
void __iomem *base;
|
||||
phys_addr_t phys_base;
|
||||
unsigned int version;
|
||||
};
|
||||
|
||||
struct hdmi_pll_data {
|
||||
|
@ -245,15 +246,24 @@ struct hdmi_pll_data {
|
|||
struct hdmi_wp_data *wp;
|
||||
};
|
||||
|
||||
struct hdmi_phy_features {
|
||||
bool bist_ctrl;
|
||||
bool ldo_voltage;
|
||||
unsigned long max_phy;
|
||||
};
|
||||
|
||||
struct hdmi_phy_data {
|
||||
void __iomem *base;
|
||||
|
||||
const struct hdmi_phy_features *features;
|
||||
u8 lane_function[4];
|
||||
u8 lane_polarity[4];
|
||||
};
|
||||
|
||||
struct hdmi_core_data {
|
||||
void __iomem *base;
|
||||
bool cts_swmode;
|
||||
bool audio_use_mclk;
|
||||
};
|
||||
|
||||
static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx,
|
||||
|
@ -303,7 +313,8 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
|
|||
struct videomode *vm);
|
||||
void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
|
||||
struct videomode *vm, struct hdmi_config *param);
|
||||
int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
|
||||
int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp,
|
||||
unsigned int version);
|
||||
phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
|
||||
|
||||
/* HDMI PLL funcs */
|
||||
|
@ -316,7 +327,8 @@ void hdmi_pll_uninit(struct hdmi_pll_data *hpll);
|
|||
int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
|
||||
unsigned long lfbitclk);
|
||||
void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
|
||||
int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
|
||||
int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy,
|
||||
unsigned int version);
|
||||
int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
|
||||
|
||||
/* HDMI common funcs */
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "omapdss.h"
|
||||
#include "hdmi4_core.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
#include "hdmi.h"
|
||||
|
||||
static struct omap_hdmi hdmi;
|
||||
|
@ -668,7 +667,7 @@ static int hdmi_audio_register(struct device *dev)
|
|||
{
|
||||
struct omap_hdmi_audio_pdata pdata = {
|
||||
.dev = dev,
|
||||
.dss_version = omapdss_get_version(),
|
||||
.version = 4,
|
||||
.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
|
||||
.ops = &hdmi_audio_ops,
|
||||
};
|
||||
|
@ -700,7 +699,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
r = hdmi_wp_init(pdev, &hdmi.wp);
|
||||
r = hdmi_wp_init(pdev, &hdmi.wp, 4);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -708,7 +707,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
r = hdmi_phy_init(pdev, &hdmi.phy);
|
||||
r = hdmi_phy_init(pdev, &hdmi.phy, 4);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -31,11 +31,11 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/sys_soc.h>
|
||||
#include <sound/asound.h>
|
||||
#include <sound/asoundef.h>
|
||||
|
||||
#include "hdmi4_core.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
#define HDMI_CORE_AV 0x500
|
||||
|
||||
|
@ -757,10 +757,10 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
|
|||
/* Audio clock regeneration settings */
|
||||
acore.n = n;
|
||||
acore.cts = cts;
|
||||
if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
|
||||
if (core->cts_swmode) {
|
||||
acore.aud_par_busclk = 0;
|
||||
acore.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
|
||||
acore.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
|
||||
acore.use_mclk = core->audio_use_mclk;
|
||||
} else {
|
||||
acore.aud_par_busclk = (((128 * 31) - 1) << 8);
|
||||
acore.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
|
||||
|
@ -884,10 +884,42 @@ void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
|
|||
hdmi_wp_audio_core_req_enable(wp, false);
|
||||
}
|
||||
|
||||
struct hdmi4_features {
|
||||
bool cts_swmode;
|
||||
bool audio_use_mclk;
|
||||
};
|
||||
|
||||
static const struct hdmi4_features hdmi4_es1_features = {
|
||||
.cts_swmode = false,
|
||||
.audio_use_mclk = false,
|
||||
};
|
||||
|
||||
static const struct hdmi4_features hdmi4_es2_features = {
|
||||
.cts_swmode = true,
|
||||
.audio_use_mclk = false,
|
||||
};
|
||||
|
||||
static const struct hdmi4_features hdmi4_es3_features = {
|
||||
.cts_swmode = true,
|
||||
.audio_use_mclk = true,
|
||||
};
|
||||
|
||||
static const struct soc_device_attribute hdmi4_soc_devices[] = {
|
||||
{ .family = "OMAP4", .revision = "ES1.?", .data = &hdmi4_es1_features },
|
||||
{ .family = "OMAP4", .revision = "ES2.?", .data = &hdmi4_es2_features },
|
||||
{ .family = "OMAP4", .data = &hdmi4_es3_features },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
|
||||
{
|
||||
const struct hdmi4_features *features;
|
||||
struct resource *res;
|
||||
|
||||
features = soc_device_match(hdmi4_soc_devices)->data;
|
||||
core->cts_swmode = features->cts_swmode;
|
||||
core->audio_use_mclk = features->audio_use_mclk;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
|
||||
core->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(core->base))
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "omapdss.h"
|
||||
#include "hdmi5_core.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static struct omap_hdmi hdmi;
|
||||
|
||||
|
@ -695,7 +694,7 @@ static int hdmi_audio_register(struct device *dev)
|
|||
{
|
||||
struct omap_hdmi_audio_pdata pdata = {
|
||||
.dev = dev,
|
||||
.dss_version = omapdss_get_version(),
|
||||
.version = 5,
|
||||
.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
|
||||
.ops = &hdmi_audio_ops,
|
||||
};
|
||||
|
@ -732,7 +731,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
r = hdmi_wp_init(pdev, &hdmi.wp);
|
||||
r = hdmi_wp_init(pdev, &hdmi.wp, 5);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -740,7 +739,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
r = hdmi_phy_init(pdev, &hdmi.phy);
|
||||
r = hdmi_phy_init(pdev, &hdmi.phy, 5);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -19,14 +19,6 @@
|
|||
#include "dss.h"
|
||||
#include "hdmi.h"
|
||||
|
||||
struct hdmi_phy_features {
|
||||
bool bist_ctrl;
|
||||
bool ldo_voltage;
|
||||
unsigned long max_phy;
|
||||
};
|
||||
|
||||
static const struct hdmi_phy_features *phy_feat;
|
||||
|
||||
void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
|
||||
{
|
||||
#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
|
||||
|
@ -36,7 +28,7 @@ void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
|
|||
DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
|
||||
DUMPPHY(HDMI_TXPHY_POWER_CTRL);
|
||||
DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
|
||||
if (phy_feat->bist_ctrl)
|
||||
if (phy->features->bist_ctrl)
|
||||
DUMPPHY(HDMI_TXPHY_BIST_CONTROL);
|
||||
}
|
||||
|
||||
|
@ -146,7 +138,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
|
|||
* In OMAP5+, the HFBITCLK must be divided by 2 before issuing the
|
||||
* HDMI_PHYPWRCMD_LDOON command.
|
||||
*/
|
||||
if (phy_feat->bist_ctrl)
|
||||
if (phy->features->bist_ctrl)
|
||||
REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11);
|
||||
|
||||
/*
|
||||
|
@ -155,7 +147,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
|
|||
*/
|
||||
if (hfbitclk != lfbitclk)
|
||||
freqout = 0;
|
||||
else if (hfbitclk / 10 < phy_feat->max_phy)
|
||||
else if (hfbitclk / 10 < phy->features->max_phy)
|
||||
freqout = 1;
|
||||
else
|
||||
freqout = 2;
|
||||
|
@ -170,7 +162,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
|
|||
hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
|
||||
|
||||
/* Setup max LDO voltage */
|
||||
if (phy_feat->ldo_voltage)
|
||||
if (phy->features->ldo_voltage)
|
||||
REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
|
||||
|
||||
hdmi_phy_configure_lanes(phy);
|
||||
|
@ -190,47 +182,15 @@ static const struct hdmi_phy_features omap54xx_phy_feats = {
|
|||
.max_phy = 186000000,
|
||||
};
|
||||
|
||||
static int hdmi_phy_init_features(struct platform_device *pdev)
|
||||
int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy,
|
||||
unsigned int version)
|
||||
{
|
||||
struct hdmi_phy_features *dst;
|
||||
const struct hdmi_phy_features *src;
|
||||
|
||||
dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
|
||||
if (!dst) {
|
||||
dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
src = &omap44xx_phy_feats;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
case OMAPDSS_VER_DRA7xx:
|
||||
src = &omap54xx_phy_feats;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
phy_feat = dst;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy)
|
||||
{
|
||||
int r;
|
||||
struct resource *res;
|
||||
|
||||
r = hdmi_phy_init_features(pdev);
|
||||
if (r)
|
||||
return r;
|
||||
if (version == 4)
|
||||
phy->features = &omap44xx_phy_feats;
|
||||
else
|
||||
phy->features = &omap54xx_phy_feats;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
|
||||
phy->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
|
|
@ -71,7 +71,7 @@ static void hdmi_pll_disable(struct dss_pll *dsspll)
|
|||
WARN_ON(r < 0 && r != -ENOSYS);
|
||||
}
|
||||
|
||||
static const struct dss_pll_ops dsi_pll_ops = {
|
||||
static const struct dss_pll_ops hdmi_pll_ops = {
|
||||
.enable = hdmi_pll_enable,
|
||||
.disable = hdmi_pll_disable,
|
||||
.set_config = dss_pll_write_config_type_b,
|
||||
|
@ -128,7 +128,8 @@ static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
|
|||
.has_refsel = true,
|
||||
};
|
||||
|
||||
static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data *hpll)
|
||||
static int hdmi_init_pll_data(struct platform_device *pdev,
|
||||
struct hdmi_pll_data *hpll)
|
||||
{
|
||||
struct dss_pll *pll = &hpll->pll;
|
||||
struct clk *clk;
|
||||
|
@ -145,23 +146,12 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data
|
|||
pll->base = hpll->base;
|
||||
pll->clkin = clk;
|
||||
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
if (hpll->wp->version == 4)
|
||||
pll->hw = &dss_omap4_hdmi_pll_hw;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
case OMAPDSS_VER_DRA7xx:
|
||||
else
|
||||
pll->hw = &dss_omap5_hdmi_pll_hw;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pll->ops = &dsi_pll_ops;
|
||||
pll->ops = &hdmi_pll_ops;
|
||||
|
||||
r = dss_pll_register(pll);
|
||||
if (r)
|
||||
|
@ -184,7 +174,7 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
|
|||
if (IS_ERR(pll->base))
|
||||
return PTR_ERR(pll->base);
|
||||
|
||||
r = dsi_init_pll_data(pdev, pll);
|
||||
r = hdmi_init_pll_data(pdev, pll);
|
||||
if (r) {
|
||||
DSSERR("failed to init HDMI PLL\n");
|
||||
return r;
|
||||
|
|
|
@ -178,9 +178,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
|
|||
* However, we don't support OMAP5 ES1 at all, so we can just check for
|
||||
* OMAP4 here.
|
||||
*/
|
||||
if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 ||
|
||||
omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||
|
||||
omapdss_get_version() == OMAPDSS_VER_OMAP4)
|
||||
if (wp->version == 4)
|
||||
hsync_len_offset = 0;
|
||||
|
||||
timing_h |= FLD_VAL(vm->hback_porch, 31, 20);
|
||||
|
@ -235,9 +233,7 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
|
|||
DSSDBG("Enter hdmi_wp_audio_config_format\n");
|
||||
|
||||
r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
|
||||
if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 ||
|
||||
omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||
|
||||
omapdss_get_version() == OMAPDSS_VER_OMAP4) {
|
||||
if (wp->version == 4) {
|
||||
r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
|
||||
r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
|
||||
}
|
||||
|
@ -282,7 +278,8 @@ int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
|
||||
int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp,
|
||||
unsigned int version)
|
||||
{
|
||||
struct resource *res;
|
||||
|
||||
|
@ -292,6 +289,7 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
|
|||
return PTR_ERR(wp->base);
|
||||
|
||||
wp->phys_base = res->start;
|
||||
wp->version = version;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <video/videomode.h>
|
||||
#include <linux/platform_data/omapdss.h>
|
||||
#include <uapi/drm/drm_mode.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
|
||||
#define DISPC_IRQ_FRAMEDONE (1 << 0)
|
||||
#define DISPC_IRQ_VSYNC (1 << 1)
|
||||
|
@ -241,13 +242,6 @@ struct omap_dss_dsi_config {
|
|||
enum omap_dss_dsi_trans_mode trans_mode;
|
||||
};
|
||||
|
||||
/* Hardcoded videomodes for tv. Venc only uses these to
|
||||
* identify the mode, and does not actually use the configs
|
||||
* itself. However, the configs should be something that
|
||||
* a normal monitor can also show */
|
||||
extern const struct videomode omap_dss_pal_vm;
|
||||
extern const struct videomode omap_dss_ntsc_vm;
|
||||
|
||||
struct omap_dss_cpr_coefs {
|
||||
s16 rr, rg, rb;
|
||||
s16 gr, gg, gb;
|
||||
|
@ -403,6 +397,14 @@ struct omapdss_hdmi_ops {
|
|||
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
|
||||
bool (*detect)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*register_hpd_cb)(struct omap_dss_device *dssdev,
|
||||
void (*cb)(void *cb_data,
|
||||
enum drm_connector_status status),
|
||||
void *cb_data);
|
||||
void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
|
||||
void (*enable_hpd)(struct omap_dss_device *dssdev);
|
||||
void (*disable_hpd)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
|
||||
int (*set_infoframe)(struct omap_dss_device *dssdev,
|
||||
const struct hdmi_avi_infoframe *avi);
|
||||
|
@ -567,12 +569,19 @@ struct omap_dss_driver {
|
|||
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
|
||||
bool (*detect)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*register_hpd_cb)(struct omap_dss_device *dssdev,
|
||||
void (*cb)(void *cb_data,
|
||||
enum drm_connector_status status),
|
||||
void *cb_data);
|
||||
void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
|
||||
void (*enable_hpd)(struct omap_dss_device *dssdev);
|
||||
void (*disable_hpd)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
|
||||
int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev,
|
||||
const struct hdmi_avi_infoframe *avi);
|
||||
};
|
||||
|
||||
enum omapdss_version omapdss_get_version(void);
|
||||
bool omapdss_is_initialized(void);
|
||||
|
||||
int omap_dss_register_driver(struct omap_dss_driver *);
|
||||
|
|
|
@ -37,10 +37,10 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include "omapdss.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
/* Venc registers */
|
||||
#define VENC_REV_ID 0x00
|
||||
|
@ -263,7 +263,7 @@ static const struct venc_config venc_config_pal_bdghi = {
|
|||
.fid_ext_start_y__fid_ext_offset_y = 0x01380005,
|
||||
};
|
||||
|
||||
const struct videomode omap_dss_pal_vm = {
|
||||
static const struct videomode omap_dss_pal_vm = {
|
||||
.hactive = 720,
|
||||
.vactive = 574,
|
||||
.pixelclock = 13500000,
|
||||
|
@ -279,9 +279,8 @@ const struct videomode omap_dss_pal_vm = {
|
|||
DISPLAY_FLAGS_PIXDATA_POSEDGE |
|
||||
DISPLAY_FLAGS_SYNC_NEGEDGE,
|
||||
};
|
||||
EXPORT_SYMBOL(omap_dss_pal_vm);
|
||||
|
||||
const struct videomode omap_dss_ntsc_vm = {
|
||||
static const struct videomode omap_dss_ntsc_vm = {
|
||||
.hactive = 720,
|
||||
.vactive = 482,
|
||||
.pixelclock = 13500000,
|
||||
|
@ -297,7 +296,6 @@ const struct videomode omap_dss_ntsc_vm = {
|
|||
DISPLAY_FLAGS_PIXDATA_POSEDGE |
|
||||
DISPLAY_FLAGS_SYNC_NEGEDGE,
|
||||
};
|
||||
EXPORT_SYMBOL(omap_dss_ntsc_vm);
|
||||
|
||||
static struct {
|
||||
struct platform_device *pdev;
|
||||
|
@ -311,6 +309,7 @@ static struct {
|
|||
struct videomode vm;
|
||||
enum omap_dss_venc_type type;
|
||||
bool invert_polarity;
|
||||
bool requires_tv_dac_clk;
|
||||
|
||||
struct omap_dss_device output;
|
||||
} venc;
|
||||
|
@ -693,7 +692,7 @@ static int venc_get_clocks(struct platform_device *pdev)
|
|||
{
|
||||
struct clk *clk;
|
||||
|
||||
if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
|
||||
if (venc.requires_tv_dac_clk) {
|
||||
clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("can't get tv_dac_clk\n");
|
||||
|
@ -828,6 +827,12 @@ static int venc_probe_of(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* VENC HW IP initialisation */
|
||||
static const struct soc_device_attribute venc_soc_devices[] = {
|
||||
{ .machine = "OMAP3[45]*" },
|
||||
{ .machine = "AM35*" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int venc_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
@ -837,6 +842,10 @@ static int venc_bind(struct device *dev, struct device *master, void *data)
|
|||
|
||||
venc.pdev = pdev;
|
||||
|
||||
/* The OMAP34xx, OMAP35xx and AM35xx VENC require the TV DAC clock. */
|
||||
if (soc_device_match(venc_soc_devices))
|
||||
venc.requires_tv_dac_clk = true;
|
||||
|
||||
mutex_init(&venc.venc_lock);
|
||||
|
||||
venc.wss_data = 0;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include "omapdss.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
struct dss_video_pll {
|
||||
struct dss_pll pll;
|
||||
|
|
|
@ -35,6 +35,23 @@ struct omap_connector {
|
|||
bool hdmi_mode;
|
||||
};
|
||||
|
||||
static void omap_connector_hpd_cb(void *cb_data,
|
||||
enum drm_connector_status status)
|
||||
{
|
||||
struct omap_connector *omap_connector = cb_data;
|
||||
struct drm_connector *connector = &omap_connector->base;
|
||||
struct drm_device *dev = connector->dev;
|
||||
enum drm_connector_status old_status;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
old_status = connector->status;
|
||||
connector->status = status;
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
if (old_status != status)
|
||||
drm_kms_helper_hotplug_event(dev);
|
||||
}
|
||||
|
||||
bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
|
||||
{
|
||||
struct omap_connector *omap_connector = to_omap_connector(connector);
|
||||
|
@ -75,6 +92,10 @@ static void omap_connector_destroy(struct drm_connector *connector)
|
|||
struct omap_dss_device *dssdev = omap_connector->dssdev;
|
||||
|
||||
DBG("%s", omap_connector->dssdev->name);
|
||||
if (connector->polled == DRM_CONNECTOR_POLL_HPD &&
|
||||
dssdev->driver->unregister_hpd_cb) {
|
||||
dssdev->driver->unregister_hpd_cb(dssdev);
|
||||
}
|
||||
drm_connector_unregister(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(omap_connector);
|
||||
|
@ -215,6 +236,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
|
|||
{
|
||||
struct drm_connector *connector = NULL;
|
||||
struct omap_connector *omap_connector;
|
||||
bool hpd_supported = false;
|
||||
|
||||
DBG("%s", dssdev->name);
|
||||
|
||||
|
@ -232,7 +254,20 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
|
|||
connector_type);
|
||||
drm_connector_helper_add(connector, &omap_connector_helper_funcs);
|
||||
|
||||
if (dssdev->driver->detect)
|
||||
if (dssdev->driver->register_hpd_cb) {
|
||||
int ret = dssdev->driver->register_hpd_cb(dssdev,
|
||||
omap_connector_hpd_cb,
|
||||
omap_connector);
|
||||
if (!ret)
|
||||
hpd_supported = true;
|
||||
else if (ret != -ENOTSUPP)
|
||||
DBG("%s: Failed to register HPD callback (%d).",
|
||||
dssdev->name, ret);
|
||||
}
|
||||
|
||||
if (hpd_supported)
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
else if (dssdev->driver->detect)
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
|
||||
DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
else
|
||||
|
|
|
@ -589,8 +589,10 @@ omap_crtc_duplicate_state(struct drm_crtc *crtc)
|
|||
current_state = to_omap_crtc_state(crtc->state);
|
||||
|
||||
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (state)
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
|
||||
|
||||
state->zpos = current_state->zpos;
|
||||
state->rotation = current_state->rotation;
|
||||
|
|
|
@ -323,6 +323,32 @@ static int omap_modeset_init(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the HPD in external components if supported
|
||||
*/
|
||||
static void omap_modeset_enable_external_hpd(void)
|
||||
{
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
for_each_dss_dev(dssdev) {
|
||||
if (dssdev->driver->enable_hpd)
|
||||
dssdev->driver->enable_hpd(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the HPD in external components if supported
|
||||
*/
|
||||
static void omap_modeset_disable_external_hpd(void)
|
||||
{
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
for_each_dss_dev(dssdev) {
|
||||
if (dssdev->driver->disable_hpd)
|
||||
dssdev->driver->disable_hpd(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* drm ioctl funcs
|
||||
*/
|
||||
|
@ -438,44 +464,11 @@ static int dev_open(struct drm_device *dev, struct drm_file *file)
|
|||
*/
|
||||
static void dev_lastclose(struct drm_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* we don't support vga_switcheroo.. so just make sure the fbdev
|
||||
* mode is active
|
||||
*/
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
DBG("lastclose: dev=%p", dev);
|
||||
|
||||
/* need to restore default rotation state.. not sure
|
||||
* if there is a cleaner way to restore properties to
|
||||
* default state? Maybe a flag that properties should
|
||||
* automatically be restored to default state on
|
||||
* lastclose?
|
||||
*/
|
||||
for (i = 0; i < priv->num_crtcs; i++) {
|
||||
struct drm_crtc *crtc = priv->crtcs[i];
|
||||
|
||||
if (!crtc->primary->rotation_property)
|
||||
continue;
|
||||
|
||||
drm_object_property_set_value(&crtc->base,
|
||||
crtc->primary->rotation_property,
|
||||
DRM_MODE_ROTATE_0);
|
||||
}
|
||||
|
||||
for (i = 0; i < priv->num_planes; i++) {
|
||||
struct drm_plane *plane = priv->planes[i];
|
||||
|
||||
if (!plane->rotation_property)
|
||||
continue;
|
||||
|
||||
drm_object_property_set_value(&plane->base,
|
||||
plane->rotation_property,
|
||||
DRM_MODE_ROTATE_0);
|
||||
}
|
||||
|
||||
if (priv->fbdev) {
|
||||
ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
|
||||
if (ret)
|
||||
|
@ -549,6 +542,12 @@ static int pdev_probe(struct platform_device *pdev)
|
|||
if (omapdss_is_initialized() == false)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to set the DMA mask\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
omap_crtc_pre_init();
|
||||
|
||||
ret = omap_connect_dssdevs();
|
||||
|
@ -602,6 +601,7 @@ static int pdev_probe(struct platform_device *pdev)
|
|||
priv->fbdev = omap_fbdev_init(ddev);
|
||||
|
||||
drm_kms_helper_poll_init(ddev);
|
||||
omap_modeset_enable_external_hpd();
|
||||
|
||||
/*
|
||||
* Register the DRM device with the core and the connectors with
|
||||
|
@ -614,6 +614,7 @@ static int pdev_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_cleanup_helpers:
|
||||
omap_modeset_disable_external_hpd();
|
||||
drm_kms_helper_poll_fini(ddev);
|
||||
if (priv->fbdev)
|
||||
omap_fbdev_free(ddev);
|
||||
|
@ -642,6 +643,7 @@ static int pdev_remove(struct platform_device *pdev)
|
|||
|
||||
drm_dev_unregister(ddev);
|
||||
|
||||
omap_modeset_disable_external_hpd();
|
||||
drm_kms_helper_poll_fini(ddev);
|
||||
|
||||
if (priv->fbdev)
|
||||
|
@ -733,7 +735,7 @@ static SIMPLE_DEV_PM_OPS(omapdrm_pm_ops, omap_drm_suspend, omap_drm_resume);
|
|||
|
||||
static struct platform_driver pdev = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.name = "omapdrm",
|
||||
.pm = &omapdrm_pm_ops,
|
||||
},
|
||||
.probe = pdev_probe,
|
||||
|
|
|
@ -379,7 +379,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
|
|||
return fb;
|
||||
|
||||
error:
|
||||
while (--i > 0)
|
||||
while (--i >= 0)
|
||||
drm_gem_object_unreference_unlocked(bos[i]);
|
||||
|
||||
return fb;
|
||||
|
|
|
@ -144,7 +144,7 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
|
|||
return omap_gem_mmap_obj(obj, vma);
|
||||
}
|
||||
|
||||
static struct dma_buf_ops omap_dmabuf_ops = {
|
||||
static const struct dma_buf_ops omap_dmabuf_ops = {
|
||||
.map_dma_buf = omap_gem_map_dma_buf,
|
||||
.unmap_dma_buf = omap_gem_unmap_dma_buf,
|
||||
.release = drm_gem_dmabuf_release,
|
||||
|
|
|
@ -664,7 +664,7 @@ static int hdmi_audio_register(struct device *dev)
|
|||
{
|
||||
struct omap_hdmi_audio_pdata pdata = {
|
||||
.dev = dev,
|
||||
.dss_version = omapdss_get_version(),
|
||||
.version = 4,
|
||||
.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
|
||||
.ops = &hdmi_audio_ops,
|
||||
};
|
||||
|
|
|
@ -695,7 +695,7 @@ static int hdmi_audio_register(struct device *dev)
|
|||
{
|
||||
struct omap_hdmi_audio_pdata pdata = {
|
||||
.dev = dev,
|
||||
.dss_version = omapdss_get_version(),
|
||||
.version = 5,
|
||||
.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
|
||||
.ops = &hdmi_audio_ops,
|
||||
};
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* DRM/KMS platform data for TI OMAP platforms
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments
|
||||
* Author: Rob Clark <rob.clark@linaro.org>
|
||||
*
|
||||
* 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 __PLATFORM_DATA_OMAP_DRM_H__
|
||||
#define __PLATFORM_DATA_OMAP_DRM_H__
|
||||
|
||||
/*
|
||||
* Optional platform data to configure the default configuration of which
|
||||
* pipes/overlays/CRTCs are used.. if this is not provided, then instead the
|
||||
* first CONFIG_DRM_OMAP_NUM_CRTCS are used, and they are each connected to
|
||||
* one manager, with priority given to managers that are connected to
|
||||
* detected devices. Remaining overlays are used as video planes. This
|
||||
* should be a good default behavior for most cases, but yet there still
|
||||
* might be times when you wish to do something different.
|
||||
*/
|
||||
struct omap_kms_platform_data {
|
||||
/* overlays to use as CRTCs: */
|
||||
int ovl_cnt;
|
||||
const int *ovl_ids;
|
||||
|
||||
/* overlays to use as video planes: */
|
||||
int pln_cnt;
|
||||
const int *pln_ids;
|
||||
|
||||
int mgr_cnt;
|
||||
const int *mgr_ids;
|
||||
|
||||
int dev_cnt;
|
||||
const char **dev_names;
|
||||
};
|
||||
|
||||
struct omap_drm_platform_data {
|
||||
uint32_t omaprev;
|
||||
struct omap_kms_platform_data *kms_pdata;
|
||||
};
|
||||
|
||||
#endif /* __PLATFORM_DATA_OMAP_DRM_H__ */
|
|
@ -39,7 +39,7 @@ struct omap_hdmi_audio_ops {
|
|||
/* HDMI audio initalization data */
|
||||
struct omap_hdmi_audio_pdata {
|
||||
struct device *dev;
|
||||
enum omapdss_version dss_version;
|
||||
unsigned int version;
|
||||
phys_addr_t audio_dma_addr;
|
||||
|
||||
const struct omap_hdmi_audio_ops *ops;
|
||||
|
|
|
@ -337,14 +337,11 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev)
|
|||
ad->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
mutex_init(&ad->current_stream_lock);
|
||||
|
||||
switch (ha->dss_version) {
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
switch (ha->version) {
|
||||
case 4:
|
||||
dai_drv = &omap4_hdmi_dai;
|
||||
break;
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
case OMAPDSS_VER_DRA7xx:
|
||||
case 5:
|
||||
dai_drv = &omap5_hdmi_dai;
|
||||
break;
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue