Commit 8824c751 authored by Dave Airlie's avatar Dave Airlie

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
  ...
parents 2040c473 2419672f
...@@ -8,7 +8,7 @@ ccflags-y := -I$(srctree)/$(src)/include \ ...@@ -8,7 +8,7 @@ ccflags-y := -I$(srctree)/$(src)/include \
# Common support # Common support
obj-y := id.o io.o control.o devices.o fb.o timer.o pm.o \ 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 \ 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 \ hwmod-common = omap_hwmod.o omap_hwmod_reset.o \
omap_hwmod_common_data.o omap_hwmod_common_data.o
......
...@@ -33,6 +33,7 @@ static void __init __maybe_unused omap_generic_init(void) ...@@ -33,6 +33,7 @@ static void __init __maybe_unused omap_generic_init(void)
pdata_quirks_init(omap_dt_match_table); pdata_quirks_init(omap_dt_match_table);
omapdss_init_of(); omapdss_init_of();
omap_soc_device_init();
} }
#ifdef CONFIG_SOC_OMAP2420 #ifdef CONFIG_SOC_OMAP2420
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
*/ */
#define FRAMEDONE_IRQ_TIMEOUT 100 #define FRAMEDONE_IRQ_TIMEOUT 100
#if defined(CONFIG_FB_OMAP2)
static struct platform_device omap_display_device = { static struct platform_device omap_display_device = {
.name = "omapdss", .name = "omapdss",
.id = -1, .id = -1,
...@@ -163,6 +164,64 @@ static enum omapdss_version __init omap_display_get_version(void) ...@@ -163,6 +164,64 @@ static enum omapdss_version __init omap_display_get_version(void)
return OMAPDSS_VER_UNKNOWN; 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) static void dispc_disable_outputs(void)
{ {
u32 v, irq_mask = 0; u32 v, irq_mask = 0;
...@@ -335,16 +394,9 @@ static struct device_node * __init omapdss_find_dss_of_node(void) ...@@ -335,16 +394,9 @@ static struct device_node * __init omapdss_find_dss_of_node(void)
int __init omapdss_init_of(void) int __init omapdss_init_of(void)
{ {
int r; int r;
enum omapdss_version ver;
struct device_node *node; struct device_node *node;
struct platform_device *pdev; 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 */ /* only create dss helper devices if dss is enabled in the .dts */
node = omapdss_find_dss_of_node(); node = omapdss_find_dss_of_node();
...@@ -354,13 +406,6 @@ int __init omapdss_init_of(void) ...@@ -354,13 +406,6 @@ int __init omapdss_init_of(void)
if (!of_device_is_available(node)) if (!of_device_is_available(node))
return 0; 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); pdev = of_find_device_by_node(node);
if (!pdev) { if (!pdev) {
...@@ -374,48 +419,5 @@ int __init omapdss_init_of(void) ...@@ -374,48 +419,5 @@ int __init omapdss_init_of(void)
return r; return r;
} }
board_data.version = ver; return omapdss_init_fbdev();
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;
} }
...@@ -26,7 +26,6 @@ struct omap_dss_dispc_dev_attr { ...@@ -26,7 +26,6 @@ struct omap_dss_dispc_dev_attr {
bool has_framedonetv_irq; bool has_framedonetv_irq;
}; };
int omap_init_drm(void);
int omap_init_vrfb(void); int omap_init_vrfb(void);
int omap_init_fb(void); int omap_init_fb(void);
int omap_init_vout(void); int omap_init_vout(void);
......
/*
* 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) ...@@ -428,7 +428,6 @@ static void __init __maybe_unused omap_hwmod_init_postsetup(void)
static void __init __maybe_unused omap_common_late_init(void) static void __init __maybe_unused omap_common_late_init(void)
{ {
omap2_common_pm_late_init(); omap2_common_pm_late_init();
omap_soc_device_init();
} }
#ifdef CONFIG_SOC_OMAP2420 #ifdef CONFIG_SOC_OMAP2420
......
...@@ -198,6 +198,9 @@ static int tvc_probe(struct platform_device *pdev) ...@@ -198,6 +198,9 @@ static int tvc_probe(struct platform_device *pdev)
struct omap_dss_device *dssdev; struct omap_dss_device *dssdev;
int r; int r;
if (!pdev->dev.of_node)
return -ENODEV;
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata) if (!ddata)
return -ENOMEM; return -ENOMEM;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/mutex.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
...@@ -37,6 +38,10 @@ static const struct videomode hdmic_default_vm = { ...@@ -37,6 +38,10 @@ static const struct videomode hdmic_default_vm = {
struct panel_drv_data { struct panel_drv_data {
struct omap_dss_device dssdev; struct omap_dss_device dssdev;
struct omap_dss_device *in; 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; struct device *dev;
...@@ -167,6 +172,70 @@ static bool hdmic_detect(struct omap_dss_device *dssdev) ...@@ -167,6 +172,70 @@ static bool hdmic_detect(struct omap_dss_device *dssdev)
return in->ops.hdmi->detect(in); 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) static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
{ {
struct panel_drv_data *ddata = to_panel_data(dssdev); struct panel_drv_data *ddata = to_panel_data(dssdev);
...@@ -197,10 +266,34 @@ static struct omap_dss_driver hdmic_driver = { ...@@ -197,10 +266,34 @@ static struct omap_dss_driver hdmic_driver = {
.read_edid = hdmic_read_edid, .read_edid = hdmic_read_edid,
.detect = hdmic_detect, .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_mode = hdmic_set_hdmi_mode,
.set_hdmi_infoframe = hdmic_set_infoframe, .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) static int hdmic_probe_of(struct platform_device *pdev)
{ {
struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct panel_drv_data *ddata = platform_get_drvdata(pdev);
...@@ -246,11 +339,22 @@ static int hdmic_probe(struct platform_device *pdev) ...@@ -246,11 +339,22 @@ static int hdmic_probe(struct platform_device *pdev)
if (r) if (r)
return r; return r;
mutex_init(&ddata->hpd_lock);
if (gpio_is_valid(ddata->hpd_gpio)) { if (gpio_is_valid(ddata->hpd_gpio)) {
r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio, r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
GPIOF_DIR_IN, "hdmi_hpd"); GPIOF_DIR_IN, "hdmi_hpd");
if (r) if (r)
goto err_reg; 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; ddata->vm = hdmic_default_vm;
......
...@@ -15,12 +15,17 @@ ...@@ -15,12 +15,17 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/mutex.h>
#include "../dss/omapdss.h" #include "../dss/omapdss.h"
struct panel_drv_data { struct panel_drv_data {
struct omap_dss_device dssdev; struct omap_dss_device dssdev;
struct omap_dss_device *in; 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 *ct_cp_hpd_gpio;
struct gpio_desc *ls_oe_gpio; struct gpio_desc *ls_oe_gpio;
...@@ -162,6 +167,49 @@ static bool tpd_detect(struct omap_dss_device *dssdev) ...@@ -162,6 +167,49 @@ static bool tpd_detect(struct omap_dss_device *dssdev)
return gpiod_get_value_cansleep(ddata->hpd_gpio); 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, static int tpd_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi) const struct hdmi_avi_infoframe *avi)
{ {
...@@ -193,10 +241,34 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = { ...@@ -193,10 +241,34 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
.read_edid = tpd_read_edid, .read_edid = tpd_read_edid,
.detect = tpd_detect, .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_infoframe = tpd_set_infoframe,
.set_hdmi_mode = tpd_set_hdmi_mode, .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) static int tpd_probe_of(struct platform_device *pdev)
{ {
struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct panel_drv_data *ddata = platform_get_drvdata(pdev);
...@@ -261,6 +333,15 @@ static int tpd_probe(struct platform_device *pdev) ...@@ -261,6 +333,15 @@ static int tpd_probe(struct platform_device *pdev)
ddata->hpd_gpio = gpio; 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 = &ddata->dssdev;
dssdev->ops.hdmi = &tpd_hdmi_ops; dssdev->ops.hdmi = &tpd_hdmi_ops;
dssdev->dev = &pdev->dev; dssdev->dev = &pdev->dev;
......
...@@ -231,6 +231,9 @@ static int panel_dpi_probe(struct platform_device *pdev) ...@@ -231,6 +231,9 @@ static int panel_dpi_probe(struct platform_device *pdev)
struct omap_dss_device *dssdev; struct omap_dss_device *dssdev;
int r; int r;
if (!pdev->dev.of_node)
return -ENODEV;
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
if (ddata == NULL) if (ddata == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -554,7 +554,7 @@ static struct attribute *dsicm_attrs[] = { ...@@ -554,7 +554,7 @@ static struct attribute *dsicm_attrs[] = {
NULL, NULL,
}; };
static struct attribute_group dsicm_attr_group = { static const struct attribute_group dsicm_attr_group = {
.attrs = dsicm_attrs, .attrs = dsicm_attrs,
}; };
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "../dss/omapdss.h" #include "../dss/omapdss.h"
static struct videomode lb035q02_vm = { static const struct videomode lb035q02_vm = {
.hactive = 320, .hactive = 320,
.vactive = 240, .vactive = 240,
......
...@@ -503,7 +503,7 @@ static struct attribute *bldev_attrs[] = { ...@@ -503,7 +503,7 @@ static struct attribute *bldev_attrs[] = {
NULL, NULL,
}; };
static struct attribute_group bldev_attr_group = { static const struct attribute_group bldev_attr_group = {
.attrs = bldev_attrs, .attrs = bldev_attrs,
}; };
...@@ -720,6 +720,9 @@ static int acx565akm_probe(struct spi_device *spi) ...@@ -720,6 +720,9 @@ static int acx565akm_probe(struct spi_device *spi)
dev_dbg(&spi->dev, "%s\n", __func__); dev_dbg(&spi->dev, "%s\n", __func__);
if (!spi->dev.of_node)
return -ENODEV;
spi->mode = SPI_MODE_3; spi->mode = SPI_MODE_3;
ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL); ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
......
...@@ -40,7 +40,7 @@ struct panel_drv_data { ...@@ -40,7 +40,7 @@ struct panel_drv_data {
struct spi_device *spi_dev; struct spi_device *spi_dev;
}; };
static struct videomode td028ttec1_panel_vm = { static const struct videomode td028ttec1_panel_vm = {
.hactive = 480, .hactive = 480,
.vactive = 640, .vactive = 640,
.pixelclock = 22153000, .pixelclock = 22153000,
......
...@@ -282,7 +282,7 @@ static struct attribute *tpo_td043_attrs[] = { ...@@ -282,7 +282,7 @@ static struct attribute *tpo_td043_attrs[] = {
NULL, NULL,
}; };
static struct attribute_group tpo_td043_attr_group = { static const struct attribute_group tpo_td043_attr_group = {
.attrs = tpo_td043_attrs, .attrs = tpo_td043_attrs,
}; };
......
...@@ -5,7 +5,7 @@ omapdss-base-y := base.o display.o dss-of.o output.o ...@@ -5,7 +5,7 @@ omapdss-base-y := base.o display.o dss-of.o output.o
obj-$(CONFIG_OMAP2_DSS) += omapdss.o obj-$(CONFIG_OMAP2_DSS) += omapdss.o
# Core DSS files # 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 pll.o video-pll.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
......
...@@ -24,182 +24,10 @@ ...@@ -24,182 +24,10 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.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 "omapdss.h"
#include "dss.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 */ /* INIT */
static int (*dss_output_drv_reg_funcs[])(void) __initdata = { static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
...@@ -236,21 +64,25 @@ static void (*dss_output_drv_unreg_funcs[])(void) = { ...@@ -236,21 +64,25 @@ static void (*dss_output_drv_unreg_funcs[])(void) = {
dss_uninit_platform_driver, dss_uninit_platform_driver,
}; };
static struct platform_device *omap_drm_device;
static int __init omap_dss_init(void) static int __init omap_dss_init(void)
{ {
int r; int r;
int i; 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) { for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
r = dss_output_drv_reg_funcs[i](); r = dss_output_drv_reg_funcs[i]();
if (r) if (r)
goto err_reg; 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; return 0;
err_reg: err_reg:
...@@ -259,8 +91,6 @@ static int __init omap_dss_init(void) ...@@ -259,8 +91,6 @@ static int __init omap_dss_init(void)
++i) ++i)
dss_output_drv_unreg_funcs[i](); dss_output_drv_unreg_funcs[i]();
platform_driver_unregister(&omap_dss_driver);
return r; return r;
} }
...@@ -268,10 +98,10 @@ static void __exit omap_dss_exit(void) ...@@ -268,10 +98,10 @@ static void __exit omap_dss_exit(void)
{ {
int i; int i;
platform_device_unregister(omap_drm_device);
for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i)
dss_output_drv_unreg_funcs[i](); dss_output_drv_unreg_funcs[i]();
platform_driver_unregister(&omap_dss_driver);
} }
module_init(omap_dss_init); module_init(omap_dss_init);
......
...@@ -39,13 +39,14 @@ ...@@ -39,13 +39,14 @@
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/sys_soc.h>
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/drm_blend.h> #include <drm/drm_blend.h>
#include "omapdss.h" #include "omapdss.h"
#include "dss.h" #include "dss.h"
#include "dss_features.h"
#include "dispc.h" #include "dispc.h"
/* DISPC */ /* DISPC */
...@@ -63,6 +64,33 @@ enum omap_burst_size { ...@@ -63,6 +64,33 @@ enum omap_burst_size {
#define REG_FLD_MOD(idx, val, start, end) \ #define REG_FLD_MOD(idx, val, start, end) \
dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
/* DISPC has feature id */
enum dispc_feature_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_HANDLE_UV_SEPARATE,
FEAT_ATTR2,
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_MFLAG,
};
struct dispc_features { struct dispc_features {
u8 sw_start; u8 sw_start;
u8 fp_start; u8 fp_start;
...@@ -76,6 +104,9 @@ struct dispc_features { ...@@ -76,6 +104,9 @@ struct dispc_features {
u16 mgr_height_max; u16 mgr_height_max;
unsigned long max_lcd_pclk; unsigned long max_lcd_pclk;
unsigned long max_tv_pclk; unsigned long max_tv_pclk;
unsigned int max_downscale;
unsigned int max_line_width;
unsigned int min_pcd;
int (*calc_scaling) (unsigned long pclk, unsigned long lclk, int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
const struct videomode *vm, const struct videomode *vm,
u16 width, u16 height, u16 out_width, u16 out_height, u16 width, u16 height, u16 out_width, u16 out_height,
...@@ -86,6 +117,16 @@ struct dispc_features { ...@@ -86,6 +117,16 @@ struct dispc_features {
u16 width, u16 height, u16 out_width, u16 out_height, u16 width, u16 height, u16 out_width, u16 out_height,
bool mem_to_mem); bool mem_to_mem);
u8 num_fifos; u8 num_fifos;
const enum dispc_feature_id *features;
unsigned int num_features;
const struct dss_reg_field *reg_fields;
const unsigned int num_reg_fields;
const enum omap_overlay_caps *overlay_caps;
const u32 **supported_color_modes;
unsigned int num_mgrs;
unsigned int num_ovls;
unsigned int buffer_size_unit;
unsigned int burst_size_unit;
/* swap GFX & WB fifos */ /* swap GFX & WB fifos */
bool gfx_fifo_workaround:1; bool gfx_fifo_workaround:1;
...@@ -180,6 +221,17 @@ enum mgr_reg_fields { ...@@ -180,6 +221,17 @@ enum mgr_reg_fields {
DISPC_MGR_FLD_NUM, DISPC_MGR_FLD_NUM,
}; };
/* DISPC register field id */
enum dispc_feat_reg_field {
FEAT_REG_FIRHINC,
FEAT_REG_FIRVINC,
FEAT_REG_FIFOHIGHTHRESHOLD,
FEAT_REG_FIFOLOWTHRESHOLD,
FEAT_REG_FIFOSIZE,
FEAT_REG_HORIZONTALACCU,
FEAT_REG_VERTICALACCU,
};
struct dispc_reg_field { struct dispc_reg_field {
u16 reg; u16 reg;
u8 high; u8 high;
...@@ -343,6 +395,38 @@ static void mgr_fld_write(enum omap_channel channel, ...@@ -343,6 +395,38 @@ static void mgr_fld_write(enum omap_channel channel,
spin_unlock_irqrestore(&dispc.control_lock, flags); spin_unlock_irqrestore(&dispc.control_lock, flags);
} }
static int dispc_get_num_ovls(void)
{
return dispc.feat->num_ovls;
}
static int dispc_get_num_mgrs(void)
{
return dispc.feat->num_mgrs;
}
static void dispc_get_reg_field(enum dispc_feat_reg_field id,
u8 *start, u8 *end)
{
if (id >= dispc.feat->num_reg_fields)
BUG();
*start = dispc.feat->reg_fields[id].start;
*end = dispc.feat->reg_fields[id].end;
}
static bool dispc_has_feature(enum dispc_feature_id id)
{
unsigned int i;
for (i = 0; i < dispc.feat->num_features; i++) {
if (dispc.feat->features[i] == id)
return true;
}
return false;
}
#define SR(reg) \ #define SR(reg) \
dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
#define RR(reg) \ #define RR(reg) \
...@@ -358,19 +442,19 @@ static void dispc_save_context(void) ...@@ -358,19 +442,19 @@ static void dispc_save_context(void)
SR(CONTROL); SR(CONTROL);
SR(CONFIG); SR(CONFIG);
SR(LINE_NUMBER); SR(LINE_NUMBER);
if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) dispc_has_feature(FEAT_ALPHA_FREE_ZORDER))
SR(GLOBAL_ALPHA); SR(GLOBAL_ALPHA);
if (dss_has_feature(FEAT_MGR_LCD2)) { if (dispc_has_feature(FEAT_MGR_LCD2)) {
SR(CONTROL2); SR(CONTROL2);
SR(CONFIG2); SR(CONFIG2);
} }
if (dss_has_feature(FEAT_MGR_LCD3)) { if (dispc_has_feature(FEAT_MGR_LCD3)) {
SR(CONTROL3); SR(CONTROL3);
SR(CONFIG3); SR(CONFIG3);
} }
for (i = 0; i < dss_feat_get_num_mgrs(); i++) { for (i = 0; i < dispc_get_num_mgrs(); i++) {
SR(DEFAULT_COLOR(i)); SR(DEFAULT_COLOR(i));
SR(TRANS_COLOR(i)); SR(TRANS_COLOR(i));
SR(SIZE_MGR(i)); SR(SIZE_MGR(i));
...@@ -385,14 +469,14 @@ static void dispc_save_context(void) ...@@ -385,14 +469,14 @@ static void dispc_save_context(void)
SR(DATA_CYCLE2(i)); SR(DATA_CYCLE2(i));
SR(DATA_CYCLE3(i)); SR(DATA_CYCLE3(i));
if (dss_has_feature(FEAT_CPR)) { if (dispc_has_feature(FEAT_CPR)) {
SR(CPR_COEF_R(i)); SR(CPR_COEF_R(i));
SR(CPR_COEF_G(i)); SR(CPR_COEF_G(i));
SR(CPR_COEF_B(i)); SR(CPR_COEF_B(i));
} }
} }
for (i = 0; i < dss_feat_get_num_ovls(); i++) { for (i = 0; i < dispc_get_num_ovls(); i++) {
SR(OVL_BA0(i)); SR(OVL_BA0(i));
SR(OVL_BA1(i)); SR(OVL_BA1(i));
SR(OVL_POSITION(i)); SR(OVL_POSITION(i));
...@@ -401,7 +485,7 @@ static void dispc_save_context(void) ...@@ -401,7 +485,7 @@ static void dispc_save_context(void)
SR(OVL_FIFO_THRESHOLD(i)); SR(OVL_FIFO_THRESHOLD(i));
SR(OVL_ROW_INC(i)); SR(OVL_ROW_INC(i));
SR(OVL_PIXEL_INC(i)); SR(OVL_PIXEL_INC(i));
if (dss_has_feature(FEAT_PRELOAD)) if (dispc_has_feature(FEAT_PRELOAD))
SR(OVL_PRELOAD(i)); SR(OVL_PRELOAD(i));
if (i == OMAP_DSS_GFX) { if (i == OMAP_DSS_GFX) {
SR(OVL_WINDOW_SKIP(i)); SR(OVL_WINDOW_SKIP(i));
...@@ -422,12 +506,12 @@ static void dispc_save_context(void) ...@@ -422,12 +506,12 @@ static void dispc_save_context(void)
for (j = 0; j < 5; j++) for (j = 0; j < 5; j++)
SR(OVL_CONV_COEF(i, j)); SR(OVL_CONV_COEF(i, j));
if (dss_has_feature(FEAT_FIR_COEF_V)) { if (dispc_has_feature(FEAT_FIR_COEF_V)) {
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
SR(OVL_FIR_COEF_V(i, j)); SR(OVL_FIR_COEF_V(i, j));
} }
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
SR(OVL_BA0_UV(i)); SR(OVL_BA0_UV(i));
SR(OVL_BA1_UV(i)); SR(OVL_BA1_UV(i));
SR(OVL_FIR2(i)); SR(OVL_FIR2(i));
...@@ -443,11 +527,11 @@ static void dispc_save_context(void) ...@@ -443,11 +527,11 @@ static void dispc_save_context(void)
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
SR(OVL_FIR_COEF_V2(i, j)); SR(OVL_FIR_COEF_V2(i, j));
} }
if (dss_has_feature(FEAT_ATTR2)) if (dispc_has_feature(FEAT_ATTR2))
SR(OVL_ATTRIBUTES2(i)); SR(OVL_ATTRIBUTES2(i));
} }
if (dss_has_feature(FEAT_CORE_CLK_DIV)) if (dispc_has_feature(FEAT_CORE_CLK_DIV))
SR(DIVISOR); SR(DIVISOR);
dispc.ctx_valid = true; dispc.ctx_valid = true;
...@@ -468,15 +552,15 @@ static void dispc_restore_context(void) ...@@ -468,15 +552,15 @@ static void dispc_restore_context(void)
/*RR(CONTROL);*/ /*RR(CONTROL);*/
RR(CONFIG); RR(CONFIG);
RR(LINE_NUMBER); RR(LINE_NUMBER);
if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) dispc_has_feature(FEAT_ALPHA_FREE_ZORDER))
RR(GLOBAL_ALPHA); RR(GLOBAL_ALPHA);
if (dss_has_feature(FEAT_MGR_LCD2)) if (dispc_has_feature(FEAT_MGR_LCD2))
RR(CONFIG2); RR(CONFIG2);
if (dss_has_feature(FEAT_MGR_LCD3)) if (dispc_has_feature(FEAT_MGR_LCD3))
RR(CONFIG3); RR(CONFIG3);
for (i = 0; i < dss_feat_get_num_mgrs(); i++) { for (i = 0; i < dispc_get_num_mgrs(); i++) {
RR(DEFAULT_COLOR(i)); RR(DEFAULT_COLOR(i));
RR(TRANS_COLOR(i)); RR(TRANS_COLOR(i));
RR(SIZE_MGR(i)); RR(SIZE_MGR(i));
...@@ -491,14 +575,14 @@ static void dispc_restore_context(void) ...@@ -491,14 +575,14 @@ static void dispc_restore_context(void)
RR(DATA_CYCLE2(i)); RR(DATA_CYCLE2(i));
RR(DATA_CYCLE3(i)); RR(DATA_CYCLE3(i));
if (dss_has_feature(FEAT_CPR)) { if (dispc_has_feature(FEAT_CPR)) {
RR(CPR_COEF_R(i)); RR(CPR_COEF_R(i));
RR(CPR_COEF_G(i)); RR(CPR_COEF_G(i));
RR(CPR_COEF_B(i)); RR(CPR_COEF_B(i));
} }
} }
for (i = 0; i < dss_feat_get_num_ovls(); i++) { for (i = 0; i < dispc_get_num_ovls(); i++) {
RR(OVL_BA0(i)); RR(OVL_BA0(i));
RR(OVL_BA1(i)); RR(OVL_BA1(i));
RR(OVL_POSITION(i)); RR(OVL_POSITION(i));
...@@ -507,7 +591,7 @@ static void dispc_restore_context(void) ...@@ -507,7 +591,7 @@ static void dispc_restore_context(void)
RR(OVL_FIFO_THRESHOLD(i)); RR(OVL_FIFO_THRESHOLD(i));
RR(OVL_ROW_INC(i)); RR(OVL_ROW_INC(i));
RR(OVL_PIXEL_INC(i)); RR(OVL_PIXEL_INC(i));
if (dss_has_feature(FEAT_PRELOAD)) if (dispc_has_feature(FEAT_PRELOAD))
RR(OVL_PRELOAD(i)); RR(OVL_PRELOAD(i));
if (i == OMAP_DSS_GFX) { if (i == OMAP_DSS_GFX) {
RR(OVL_WINDOW_SKIP(i)); RR(OVL_WINDOW_SKIP(i));
...@@ -528,12 +612,12 @@ static void dispc_restore_context(void) ...@@ -528,12 +612,12 @@ static void dispc_restore_context(void)
for (j = 0; j < 5; j++) for (j = 0; j < 5; j++)
RR(OVL_CONV_COEF(i, j)); RR(OVL_CONV_COEF(i, j));
if (dss_has_feature(FEAT_FIR_COEF_V)) { if (dispc_has_feature(FEAT_FIR_COEF_V)) {
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
RR(OVL_FIR_COEF_V(i, j)); RR(OVL_FIR_COEF_V(i, j));
} }
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
RR(OVL_BA0_UV(i)); RR(OVL_BA0_UV(i));
RR(OVL_BA1_UV(i)); RR(OVL_BA1_UV(i));
RR(OVL_FIR2(i)); RR(OVL_FIR2(i));
...@@ -549,18 +633,18 @@ static void dispc_restore_context(void) ...@@ -549,18 +633,18 @@ static void dispc_restore_context(void)
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
RR(OVL_FIR_COEF_V2(i, j)); RR(OVL_FIR_COEF_V2(i, j));
} }
if (dss_has_feature(FEAT_ATTR2)) if (dispc_has_feature(FEAT_ATTR2))
RR(OVL_ATTRIBUTES2(i)); RR(OVL_ATTRIBUTES2(i));
} }
if (dss_has_feature(FEAT_CORE_CLK_DIV)) if (dispc_has_feature(FEAT_CORE_CLK_DIV))
RR(DIVISOR); RR(DIVISOR);
/* enable last, because LCD & DIGIT enable are here */ /* enable last, because LCD & DIGIT enable are here */
RR(CONTROL); RR(CONTROL);
if (dss_has_feature(FEAT_MGR_LCD2)) if (dispc_has_feature(FEAT_MGR_LCD2))
RR(CONTROL2); RR(CONTROL2);
if (dss_has_feature(FEAT_MGR_LCD3)) if (dispc_has_feature(FEAT_MGR_LCD3))
RR(CONTROL3); RR(CONTROL3);
/* clear spurious SYNC_LOST_DIGIT interrupts */ /* clear spurious SYNC_LOST_DIGIT interrupts */
dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT); dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
...@@ -779,7 +863,7 @@ static void dispc_ovl_write_color_conv_coef(enum omap_plane_id plane, ...@@ -779,7 +863,7 @@ static void dispc_ovl_write_color_conv_coef(enum omap_plane_id plane,
static void dispc_setup_color_conv_coef(void) static void dispc_setup_color_conv_coef(void)
{ {
int i; int i;
int num_ovl = dss_feat_get_num_ovls(); int num_ovl = dispc_get_num_ovls();
const struct color_conv_coef ctbl_bt601_5_ovl = { const struct color_conv_coef ctbl_bt601_5_ovl = {
/* YUV -> RGB */ /* YUV -> RGB */
298, 409, 0, 298, -208, -100, 298, 0, 517, 0, 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
...@@ -868,10 +952,10 @@ static void dispc_ovl_enable_zorder_planes(void) ...@@ -868,10 +952,10 @@ static void dispc_ovl_enable_zorder_planes(void)
{ {
int i; int i;
if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) if (!dispc_has_feature(FEAT_ALPHA_FREE_ZORDER))
return; return;
for (i = 0; i < dss_feat_get_num_ovls(); i++) for (i = 0; i < dispc_get_num_ovls(); i++)
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
} }
...@@ -994,7 +1078,7 @@ static bool format_is_yuv(u32 fourcc) ...@@ -994,7 +1078,7 @@ static bool format_is_yuv(u32 fourcc)
static void dispc_ovl_configure_burst_type(enum omap_plane_id plane, static void dispc_ovl_configure_burst_type(enum omap_plane_id plane,
enum omap_dss_rotation_type rotation_type) enum omap_dss_rotation_type rotation_type)
{ {
if (dss_has_feature(FEAT_BURST_2D) == 0) if (dispc_has_feature(FEAT_BURST_2D) == 0)
return; return;
if (rotation_type == OMAP_DSS_ROT_TILER) if (rotation_type == OMAP_DSS_ROT_TILER)
...@@ -1025,7 +1109,7 @@ static void dispc_ovl_set_channel_out(enum omap_plane_id plane, ...@@ -1025,7 +1109,7 @@ static void dispc_ovl_set_channel_out(enum omap_plane_id plane,
} }
val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
if (dss_has_feature(FEAT_MGR_LCD2)) { if (dispc_has_feature(FEAT_MGR_LCD2)) {
switch (channel) { switch (channel) {
case OMAP_DSS_CHANNEL_LCD: case OMAP_DSS_CHANNEL_LCD:
chan = 0; chan = 0;
...@@ -1040,7 +1124,7 @@ static void dispc_ovl_set_channel_out(enum omap_plane_id plane, ...@@ -1040,7 +1124,7 @@ static void dispc_ovl_set_channel_out(enum omap_plane_id plane,
chan2 = 1; chan2 = 1;
break; break;
case OMAP_DSS_CHANNEL_LCD3: case OMAP_DSS_CHANNEL_LCD3:
if (dss_has_feature(FEAT_MGR_LCD3)) { if (dispc_has_feature(FEAT_MGR_LCD3)) {
chan = 0; chan = 0;
chan2 = 2; chan2 = 2;
} else { } else {
...@@ -1089,7 +1173,7 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane_id plane) ...@@ -1089,7 +1173,7 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane_id plane)
if (FLD_GET(val, shift, shift) == 1) if (FLD_GET(val, shift, shift) == 1)
return OMAP_DSS_CHANNEL_DIGIT; return OMAP_DSS_CHANNEL_DIGIT;
if (!dss_has_feature(FEAT_MGR_LCD2)) if (!dispc_has_feature(FEAT_MGR_LCD2))
return OMAP_DSS_CHANNEL_LCD; return OMAP_DSS_CHANNEL_LCD;
switch (FLD_GET(val, 31, 30)) { switch (FLD_GET(val, 31, 30)) {
...@@ -1128,7 +1212,7 @@ static void dispc_configure_burst_sizes(void) ...@@ -1128,7 +1212,7 @@ static void dispc_configure_burst_sizes(void)
const int burst_size = BURST_SIZE_X8; const int burst_size = BURST_SIZE_X8;
/* Configure burst size always to maximum size */ /* Configure burst size always to maximum size */
for (i = 0; i < dss_feat_get_num_ovls(); ++i) for (i = 0; i < dispc_get_num_ovls(); ++i)
dispc_ovl_set_burst_size(i, burst_size); dispc_ovl_set_burst_size(i, burst_size);
if (dispc.feat->has_writeback) if (dispc.feat->has_writeback)
dispc_ovl_set_burst_size(OMAP_DSS_WB, burst_size); dispc_ovl_set_burst_size(OMAP_DSS_WB, burst_size);
...@@ -1136,19 +1220,28 @@ static void dispc_configure_burst_sizes(void) ...@@ -1136,19 +1220,28 @@ static void dispc_configure_burst_sizes(void)
static u32 dispc_ovl_get_burst_size(enum omap_plane_id plane) static u32 dispc_ovl_get_burst_size(enum omap_plane_id plane)
{ {
unsigned unit = dss_feat_get_burst_size_unit();
/* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
return unit * 8; return dispc.feat->burst_size_unit * 8;
} }
static const u32 *dispc_ovl_get_color_modes(enum omap_plane_id plane) static bool dispc_ovl_color_mode_supported(enum omap_plane_id plane, u32 fourcc)
{ {
return dss_feat_get_supported_color_modes(plane); const u32 *modes;
unsigned int i;
modes = dispc.feat->supported_color_modes[plane];
for (i = 0; modes[i]; ++i) {
if (modes[i] == fourcc)
return true;
}
return false;
} }
static int dispc_get_num_ovls(void) static const u32 *dispc_ovl_get_color_modes(enum omap_plane_id plane)
{ {
return dss_feat_get_num_ovls(); return dispc.feat->supported_color_modes[plane];
} }
static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
...@@ -1223,9 +1316,9 @@ static void dispc_init_fifos(void) ...@@ -1223,9 +1316,9 @@ static void dispc_init_fifos(void)
u32 unit; u32 unit;
int i; int i;
unit = dss_feat_get_buffer_size_unit(); unit = dispc.feat->buffer_size_unit;
dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); dispc_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) { for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end); size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
...@@ -1265,7 +1358,7 @@ static void dispc_init_fifos(void) ...@@ -1265,7 +1358,7 @@ static void dispc_init_fifos(void)
/* /*
* Setup default fifo thresholds. * Setup default fifo thresholds.
*/ */
for (i = 0; i < dss_feat_get_num_ovls(); ++i) { for (i = 0; i < dispc_get_num_ovls(); ++i) {
u32 low, high; u32 low, high;
const bool use_fifomerge = false; const bool use_fifomerge = false;
const bool manual_update = false; const bool manual_update = false;
...@@ -1307,7 +1400,7 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, ...@@ -1307,7 +1400,7 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low,
u8 hi_start, hi_end, lo_start, lo_end; u8 hi_start, hi_end, lo_start, lo_end;
u32 unit; u32 unit;
unit = dss_feat_get_buffer_size_unit(); unit = dispc.feat->buffer_size_unit;
WARN_ON(low % unit != 0); WARN_ON(low % unit != 0);
WARN_ON(high % unit != 0); WARN_ON(high % unit != 0);
...@@ -1315,8 +1408,8 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, ...@@ -1315,8 +1408,8 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low,
low /= unit; low /= unit;
high /= unit; high /= unit;
dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); dispc_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); dispc_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n", DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n",
plane, plane,
...@@ -1335,14 +1428,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, ...@@ -1335,14 +1428,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low,
* large for the preload field, set the threshold to the maximum value * large for the preload field, set the threshold to the maximum value
* that can be held by the preload register * that can be held by the preload register
*/ */
if (dss_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload && if (dispc_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload &&
plane != OMAP_DSS_WB) plane != OMAP_DSS_WB)
dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu)); dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu));
} }
void dispc_enable_fifomerge(bool enable) void dispc_enable_fifomerge(bool enable)
{ {
if (!dss_has_feature(FEAT_FIFO_MERGE)) { if (!dispc_has_feature(FEAT_FIFO_MERGE)) {
WARN_ON(enable); WARN_ON(enable);
return; return;
} }
...@@ -1360,7 +1453,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, ...@@ -1360,7 +1453,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane,
* buffer_units, and the fifo thresholds must be buffer_unit aligned. * buffer_units, and the fifo thresholds must be buffer_unit aligned.
*/ */
unsigned buf_unit = dss_feat_get_buffer_size_unit(); unsigned buf_unit = dispc.feat->buffer_size_unit;
unsigned ovl_fifo_size, total_fifo_size, burst_size; unsigned ovl_fifo_size, total_fifo_size, burst_size;
int i; int i;
...@@ -1369,7 +1462,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, ...@@ -1369,7 +1462,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane,
if (use_fifomerge) { if (use_fifomerge) {
total_fifo_size = 0; total_fifo_size = 0;
for (i = 0; i < dss_feat_get_num_ovls(); ++i) for (i = 0; i < dispc_get_num_ovls(); ++i)
total_fifo_size += dispc_ovl_get_fifo_size(i); total_fifo_size += dispc_ovl_get_fifo_size(i);
} else { } else {
total_fifo_size = ovl_fifo_size; total_fifo_size = ovl_fifo_size;
...@@ -1381,7 +1474,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, ...@@ -1381,7 +1474,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane,
* combined fifo size * combined fifo size
*/ */
if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { if (manual_update && dispc_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
*fifo_low = ovl_fifo_size - burst_size * 2; *fifo_low = ovl_fifo_size - burst_size * 2;
*fifo_high = total_fifo_size - burst_size; *fifo_high = total_fifo_size - burst_size;
} else if (plane == OMAP_DSS_WB) { } else if (plane == OMAP_DSS_WB) {
...@@ -1435,9 +1528,9 @@ static void dispc_init_mflag(void) ...@@ -1435,9 +1528,9 @@ static void dispc_init_mflag(void)
(1 << 0) | /* MFLAG_CTRL = force always on */ (1 << 0) | /* MFLAG_CTRL = force always on */
(0 << 2)); /* MFLAG_START = disable */ (0 << 2)); /* MFLAG_START = disable */
for (i = 0; i < dss_feat_get_num_ovls(); ++i) { for (i = 0; i < dispc_get_num_ovls(); ++i) {
u32 size = dispc_ovl_get_fifo_size(i); u32 size = dispc_ovl_get_fifo_size(i);
u32 unit = dss_feat_get_buffer_size_unit(); u32 unit = dispc.feat->buffer_size_unit;
u32 low, high; u32 low, high;
dispc_ovl_set_mflag(i, true); dispc_ovl_set_mflag(i, true);
...@@ -1456,7 +1549,7 @@ static void dispc_init_mflag(void) ...@@ -1456,7 +1549,7 @@ static void dispc_init_mflag(void)
if (dispc.feat->has_writeback) { if (dispc.feat->has_writeback) {
u32 size = dispc_ovl_get_fifo_size(OMAP_DSS_WB); u32 size = dispc_ovl_get_fifo_size(OMAP_DSS_WB);
u32 unit = dss_feat_get_buffer_size_unit(); u32 unit = dispc.feat->buffer_size_unit;
u32 low, high; u32 low, high;
dispc_ovl_set_mflag(OMAP_DSS_WB, true); dispc_ovl_set_mflag(OMAP_DSS_WB, true);
...@@ -1483,10 +1576,8 @@ static void dispc_ovl_set_fir(enum omap_plane_id plane, ...@@ -1483,10 +1576,8 @@ static void dispc_ovl_set_fir(enum omap_plane_id plane,
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
u8 hinc_start, hinc_end, vinc_start, vinc_end; u8 hinc_start, hinc_end, vinc_start, vinc_end;
dss_feat_get_reg_field(FEAT_REG_FIRHINC, dispc_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end);
&hinc_start, &hinc_end); dispc_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end);
dss_feat_get_reg_field(FEAT_REG_FIRVINC,
&vinc_start, &vinc_end);
val = FLD_VAL(vinc, vinc_start, vinc_end) | val = FLD_VAL(vinc, vinc_start, vinc_end) |
FLD_VAL(hinc, hinc_start, hinc_end); FLD_VAL(hinc, hinc_start, hinc_end);
...@@ -1503,8 +1594,8 @@ static void dispc_ovl_set_vid_accu0(enum omap_plane_id plane, int haccu, ...@@ -1503,8 +1594,8 @@ static void dispc_ovl_set_vid_accu0(enum omap_plane_id plane, int haccu,
u32 val; u32 val;
u8 hor_start, hor_end, vert_start, vert_end; u8 hor_start, hor_end, vert_start, vert_end;
dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); dispc_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); dispc_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
val = FLD_VAL(vaccu, vert_start, vert_end) | val = FLD_VAL(vaccu, vert_start, vert_end) |
FLD_VAL(haccu, hor_start, hor_end); FLD_VAL(haccu, hor_start, hor_end);
...@@ -1518,8 +1609,8 @@ static void dispc_ovl_set_vid_accu1(enum omap_plane_id plane, int haccu, ...@@ -1518,8 +1609,8 @@ static void dispc_ovl_set_vid_accu1(enum omap_plane_id plane, int haccu,
u32 val; u32 val;
u8 hor_start, hor_end, vert_start, vert_end; u8 hor_start, hor_end, vert_start, vert_end;
dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); dispc_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); dispc_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
val = FLD_VAL(vaccu, vert_start, vert_end) | val = FLD_VAL(vaccu, vert_start, vert_end) |
FLD_VAL(haccu, hor_start, hor_end); FLD_VAL(haccu, hor_start, hor_end);
...@@ -1671,14 +1762,14 @@ static void dispc_ovl_set_scaling_common(enum omap_plane_id plane, ...@@ -1671,14 +1762,14 @@ static void dispc_ovl_set_scaling_common(enum omap_plane_id plane,
l |= five_taps ? (1 << 21) : 0; l |= five_taps ? (1 << 21) : 0;
/* VRESIZECONF and HRESIZECONF */ /* VRESIZECONF and HRESIZECONF */
if (dss_has_feature(FEAT_RESIZECONF)) { if (dispc_has_feature(FEAT_RESIZECONF)) {
l &= ~(0x3 << 7); l &= ~(0x3 << 7);
l |= (orig_width <= out_width) ? 0 : (1 << 7); l |= (orig_width <= out_width) ? 0 : (1 << 7);
l |= (orig_height <= out_height) ? 0 : (1 << 8); l |= (orig_height <= out_height) ? 0 : (1 << 8);
} }
/* LINEBUFFERSPLIT */ /* LINEBUFFERSPLIT */
if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) { if (dispc_has_feature(FEAT_LINEBUFFERSPLIT)) {
l &= ~(0x1 << 22); l &= ~(0x1 << 22);
l |= five_taps ? (1 << 22) : 0; l |= five_taps ? (1 << 22) : 0;
} }
...@@ -1713,7 +1804,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane_id plane, ...@@ -1713,7 +1804,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane_id plane,
int scale_y = out_height != orig_height; int scale_y = out_height != orig_height;
bool chroma_upscale = plane != OMAP_DSS_WB; bool chroma_upscale = plane != OMAP_DSS_WB;
if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) if (!dispc_has_feature(FEAT_HANDLE_UV_SEPARATE))
return; return;
if (!format_is_yuv(fourcc)) { if (!format_is_yuv(fourcc)) {
...@@ -1860,11 +1951,11 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane_id plane, u8 rotation, ...@@ -1860,11 +1951,11 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane_id plane, u8 rotation,
vidrot = 1; vidrot = 1;
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
if (dss_has_feature(FEAT_ROWREPEATENABLE)) if (dispc_has_feature(FEAT_ROWREPEATENABLE))
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
row_repeat ? 1 : 0, 18, 18); row_repeat ? 1 : 0, 18, 18);
if (dss_feat_color_mode_supported(plane, DRM_FORMAT_NV12)) { if (dispc_ovl_color_mode_supported(plane, DRM_FORMAT_NV12)) {
bool doublestride = bool doublestride =
fourcc == DRM_FORMAT_NV12 && fourcc == DRM_FORMAT_NV12 &&
rotation_type == OMAP_DSS_ROT_TILER && rotation_type == OMAP_DSS_ROT_TILER &&
...@@ -2118,8 +2209,7 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, ...@@ -2118,8 +2209,7 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
int error; int error;
u16 in_width, in_height; u16 in_width, in_height;
int min_factor = min(*decim_x, *decim_y); int min_factor = min(*decim_x, *decim_y);
const int maxsinglelinewidth = const int maxsinglelinewidth = dispc.feat->max_line_width;
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
*five_taps = false; *five_taps = false;
...@@ -2163,8 +2253,7 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, ...@@ -2163,8 +2253,7 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
{ {
int error; int error;
u16 in_width, in_height; u16 in_width, in_height;
const int maxsinglelinewidth = const int maxsinglelinewidth = dispc.feat->max_line_width;
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
do { do {
in_height = height / *decim_y; in_height = height / *decim_y;
...@@ -2249,9 +2338,8 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, ...@@ -2249,9 +2338,8 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
u16 in_width, in_width_max; u16 in_width, in_width_max;
int decim_x_min = *decim_x; int decim_x_min = *decim_x;
u16 in_height = height / *decim_y; u16 in_height = height / *decim_y;
const int maxsinglelinewidth = const int maxsinglelinewidth = dispc.feat->max_line_width;
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); const int maxdownscale = dispc.feat->max_downscale;
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
if (mem_to_mem) { if (mem_to_mem) {
in_width_max = out_width * maxdownscale; in_width_max = out_width * maxdownscale;
...@@ -2311,7 +2399,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, ...@@ -2311,7 +2399,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
int *x_predecim, int *y_predecim, u16 pos_x, int *x_predecim, int *y_predecim, u16 pos_x,
enum omap_dss_rotation_type rotation_type, bool mem_to_mem) enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
{ {
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); const int maxdownscale = dispc.feat->max_downscale;
const int max_decim_limit = 16; const int max_decim_limit = 16;
unsigned long core_clk = 0; unsigned long core_clk = 0;
int decim_x, decim_y, ret; int decim_x, decim_y, ret;
...@@ -2332,7 +2420,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, ...@@ -2332,7 +2420,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
} else { } else {
*x_predecim = max_decim_limit; *x_predecim = max_decim_limit;
*y_predecim = (rotation_type == OMAP_DSS_ROT_TILER && *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
dss_has_feature(FEAT_BURST_2D)) ? dispc_has_feature(FEAT_BURST_2D)) ?
2 : max_decim_limit; 2 : max_decim_limit;
} }
...@@ -2428,7 +2516,7 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, ...@@ -2428,7 +2516,7 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane,
out_height); out_height);
} }
if (!dss_feat_color_mode_supported(plane, fourcc)) if (!dispc_ovl_color_mode_supported(plane, fourcc))
return -EINVAL; return -EINVAL;
r = dispc_ovl_calc_scaling(pclk, lclk, caps, vm, in_width, r = dispc_ovl_calc_scaling(pclk, lclk, caps, vm, in_width,
...@@ -2549,7 +2637,7 @@ static int dispc_ovl_setup(enum omap_plane_id plane, ...@@ -2549,7 +2637,7 @@ static int dispc_ovl_setup(enum omap_plane_id plane,
enum omap_channel channel) enum omap_channel channel)
{ {
int r; int r;
enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane); enum omap_overlay_caps caps = dispc.feat->overlay_caps[plane];
const bool replication = true; const bool replication = true;
DSSDBG("dispc_ovl_setup %d, pa %pad, pa_uv %pad, sw %d, %d,%d, %dx%d ->" DSSDBG("dispc_ovl_setup %d, pa %pad, pa_uv %pad, sw %d, %d,%d, %dx%d ->"
...@@ -2647,12 +2735,12 @@ static int dispc_ovl_enable(enum omap_plane_id plane, bool enable) ...@@ -2647,12 +2735,12 @@ static int dispc_ovl_enable(enum omap_plane_id plane, bool enable)
static enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel) static enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel)
{ {
return dss_feat_get_supported_outputs(channel); return dss_get_supported_outputs(channel);
} }
static void dispc_lcd_enable_signal_polarity(bool act_high) static void dispc_lcd_enable_signal_polarity(bool act_high)
{ {
if (!dss_has_feature(FEAT_LCDENABLEPOL)) if (!dispc_has_feature(FEAT_LCDENABLEPOL))
return; return;
REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
...@@ -2660,7 +2748,7 @@ static void dispc_lcd_enable_signal_polarity(bool act_high) ...@@ -2660,7 +2748,7 @@ static void dispc_lcd_enable_signal_polarity(bool act_high)
void dispc_lcd_enable_signal(bool enable) void dispc_lcd_enable_signal(bool enable)
{ {
if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) if (!dispc_has_feature(FEAT_LCDENABLESIGNAL))
return; return;
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
...@@ -2668,17 +2756,12 @@ void dispc_lcd_enable_signal(bool enable) ...@@ -2668,17 +2756,12 @@ void dispc_lcd_enable_signal(bool enable)
void dispc_pck_free_enable(bool enable) void dispc_pck_free_enable(bool enable)
{ {
if (!dss_has_feature(FEAT_PCKFREEENABLE)) if (!dispc_has_feature(FEAT_PCKFREEENABLE))
return; return;
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
} }
static int dispc_get_num_mgrs(void)
{
return dss_feat_get_num_mgrs();
}
static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
{ {
mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable); mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
...@@ -2718,7 +2801,7 @@ static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) ...@@ -2718,7 +2801,7 @@ static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
bool enable) bool enable)
{ {
if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) if (!dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER))
return; return;
if (ch == OMAP_DSS_CHANNEL_LCD) if (ch == OMAP_DSS_CHANNEL_LCD)
...@@ -2735,7 +2818,7 @@ static void dispc_mgr_setup(enum omap_channel channel, ...@@ -2735,7 +2818,7 @@ static void dispc_mgr_setup(enum omap_channel channel,
dispc_mgr_enable_trans_key(channel, info->trans_enabled); dispc_mgr_enable_trans_key(channel, info->trans_enabled);
dispc_mgr_enable_alpha_fixed_zorder(channel, dispc_mgr_enable_alpha_fixed_zorder(channel,
info->partial_alpha_enabled); info->partial_alpha_enabled);
if (dss_has_feature(FEAT_CPR)) { if (dispc_has_feature(FEAT_CPR)) {
dispc_mgr_enable_cpr(channel, info->cpr_enable); dispc_mgr_enable_cpr(channel, info->cpr_enable);
dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
} }
...@@ -3013,7 +3096,7 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, ...@@ -3013,7 +3096,7 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
dispc_write_reg(DISPC_DIVISORo(channel), dispc_write_reg(DISPC_DIVISORo(channel),
FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
if (!dss_has_feature(FEAT_CORE_CLK_DIV) && if (!dispc_has_feature(FEAT_CORE_CLK_DIV) &&
channel == OMAP_DSS_CHANNEL_LCD) channel == OMAP_DSS_CHANNEL_LCD)
dispc.core_clk_rate = dispc_fclk_rate() / lck_div; dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
} }
...@@ -3168,7 +3251,7 @@ void dispc_dump_clocks(struct seq_file *s) ...@@ -3168,7 +3251,7 @@ void dispc_dump_clocks(struct seq_file *s)
seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
if (dss_has_feature(FEAT_CORE_CLK_DIV)) { if (dispc_has_feature(FEAT_CORE_CLK_DIV)) {
seq_printf(s, "- DISPC-CORE-CLK -\n"); seq_printf(s, "- DISPC-CORE-CLK -\n");
l = dispc_read_reg(DISPC_DIVISOR); l = dispc_read_reg(DISPC_DIVISOR);
lcd = FLD_GET(l, 23, 16); lcd = FLD_GET(l, 23, 16);
...@@ -3179,9 +3262,9 @@ void dispc_dump_clocks(struct seq_file *s) ...@@ -3179,9 +3262,9 @@ void dispc_dump_clocks(struct seq_file *s)
dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD); dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD);
if (dss_has_feature(FEAT_MGR_LCD2)) if (dispc_has_feature(FEAT_MGR_LCD2))
dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD2); dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD2);
if (dss_has_feature(FEAT_MGR_LCD3)) if (dispc_has_feature(FEAT_MGR_LCD3))
dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD3); dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD3);
dispc_runtime_put(); dispc_runtime_put();
...@@ -3221,18 +3304,18 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3221,18 +3304,18 @@ static void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_CAPABLE); DUMPREG(DISPC_CAPABLE);
DUMPREG(DISPC_LINE_STATUS); DUMPREG(DISPC_LINE_STATUS);
DUMPREG(DISPC_LINE_NUMBER); DUMPREG(DISPC_LINE_NUMBER);
if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) dispc_has_feature(FEAT_ALPHA_FREE_ZORDER))
DUMPREG(DISPC_GLOBAL_ALPHA); DUMPREG(DISPC_GLOBAL_ALPHA);
if (dss_has_feature(FEAT_MGR_LCD2)) { if (dispc_has_feature(FEAT_MGR_LCD2)) {
DUMPREG(DISPC_CONTROL2); DUMPREG(DISPC_CONTROL2);
DUMPREG(DISPC_CONFIG2); DUMPREG(DISPC_CONFIG2);
} }
if (dss_has_feature(FEAT_MGR_LCD3)) { if (dispc_has_feature(FEAT_MGR_LCD3)) {
DUMPREG(DISPC_CONTROL3); DUMPREG(DISPC_CONTROL3);
DUMPREG(DISPC_CONFIG3); DUMPREG(DISPC_CONFIG3);
} }
if (dss_has_feature(FEAT_MFLAG)) if (dispc_has_feature(FEAT_MFLAG))
DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE); DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE);
#undef DUMPREG #undef DUMPREG
...@@ -3245,7 +3328,7 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3245,7 +3328,7 @@ static void dispc_dump_regs(struct seq_file *s)
p_names = mgr_names; p_names = mgr_names;
/* DISPC channel specific registers */ /* DISPC channel specific registers */
for (i = 0; i < dss_feat_get_num_mgrs(); i++) { for (i = 0; i < dispc_get_num_mgrs(); i++) {
DUMPREG(i, DISPC_DEFAULT_COLOR); DUMPREG(i, DISPC_DEFAULT_COLOR);
DUMPREG(i, DISPC_TRANS_COLOR); DUMPREG(i, DISPC_TRANS_COLOR);
DUMPREG(i, DISPC_SIZE_MGR); DUMPREG(i, DISPC_SIZE_MGR);
...@@ -3262,7 +3345,7 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3262,7 +3345,7 @@ static void dispc_dump_regs(struct seq_file *s)
DUMPREG(i, DISPC_DATA_CYCLE2); DUMPREG(i, DISPC_DATA_CYCLE2);
DUMPREG(i, DISPC_DATA_CYCLE3); DUMPREG(i, DISPC_DATA_CYCLE3);
if (dss_has_feature(FEAT_CPR)) { if (dispc_has_feature(FEAT_CPR)) {
DUMPREG(i, DISPC_CPR_COEF_R); DUMPREG(i, DISPC_CPR_COEF_R);
DUMPREG(i, DISPC_CPR_COEF_G); DUMPREG(i, DISPC_CPR_COEF_G);
DUMPREG(i, DISPC_CPR_COEF_B); DUMPREG(i, DISPC_CPR_COEF_B);
...@@ -3271,7 +3354,7 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3271,7 +3354,7 @@ static void dispc_dump_regs(struct seq_file *s)
p_names = ovl_names; p_names = ovl_names;
for (i = 0; i < dss_feat_get_num_ovls(); i++) { for (i = 0; i < dispc_get_num_ovls(); i++) {
DUMPREG(i, DISPC_OVL_BA0); DUMPREG(i, DISPC_OVL_BA0);
DUMPREG(i, DISPC_OVL_BA1); DUMPREG(i, DISPC_OVL_BA1);
DUMPREG(i, DISPC_OVL_POSITION); DUMPREG(i, DISPC_OVL_POSITION);
...@@ -3282,9 +3365,9 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3282,9 +3365,9 @@ static void dispc_dump_regs(struct seq_file *s)
DUMPREG(i, DISPC_OVL_ROW_INC); DUMPREG(i, DISPC_OVL_ROW_INC);
DUMPREG(i, DISPC_OVL_PIXEL_INC); DUMPREG(i, DISPC_OVL_PIXEL_INC);
if (dss_has_feature(FEAT_PRELOAD)) if (dispc_has_feature(FEAT_PRELOAD))
DUMPREG(i, DISPC_OVL_PRELOAD); DUMPREG(i, DISPC_OVL_PRELOAD);
if (dss_has_feature(FEAT_MFLAG)) if (dispc_has_feature(FEAT_MFLAG))
DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD); DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD);
if (i == OMAP_DSS_GFX) { if (i == OMAP_DSS_GFX) {
...@@ -3297,14 +3380,14 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3297,14 +3380,14 @@ static void dispc_dump_regs(struct seq_file *s)
DUMPREG(i, DISPC_OVL_PICTURE_SIZE); DUMPREG(i, DISPC_OVL_PICTURE_SIZE);
DUMPREG(i, DISPC_OVL_ACCU0); DUMPREG(i, DISPC_OVL_ACCU0);
DUMPREG(i, DISPC_OVL_ACCU1); DUMPREG(i, DISPC_OVL_ACCU1);
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
DUMPREG(i, DISPC_OVL_BA0_UV); DUMPREG(i, DISPC_OVL_BA0_UV);
DUMPREG(i, DISPC_OVL_BA1_UV); DUMPREG(i, DISPC_OVL_BA1_UV);
DUMPREG(i, DISPC_OVL_FIR2); DUMPREG(i, DISPC_OVL_FIR2);
DUMPREG(i, DISPC_OVL_ACCU2_0); DUMPREG(i, DISPC_OVL_ACCU2_0);
DUMPREG(i, DISPC_OVL_ACCU2_1); DUMPREG(i, DISPC_OVL_ACCU2_1);
} }
if (dss_has_feature(FEAT_ATTR2)) if (dispc_has_feature(FEAT_ATTR2))
DUMPREG(i, DISPC_OVL_ATTRIBUTES2); DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
} }
...@@ -3319,21 +3402,21 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3319,21 +3402,21 @@ static void dispc_dump_regs(struct seq_file *s)
DUMPREG(i, DISPC_OVL_ROW_INC); DUMPREG(i, DISPC_OVL_ROW_INC);
DUMPREG(i, DISPC_OVL_PIXEL_INC); DUMPREG(i, DISPC_OVL_PIXEL_INC);
if (dss_has_feature(FEAT_MFLAG)) if (dispc_has_feature(FEAT_MFLAG))
DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD); DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD);
DUMPREG(i, DISPC_OVL_FIR); DUMPREG(i, DISPC_OVL_FIR);
DUMPREG(i, DISPC_OVL_PICTURE_SIZE); DUMPREG(i, DISPC_OVL_PICTURE_SIZE);
DUMPREG(i, DISPC_OVL_ACCU0); DUMPREG(i, DISPC_OVL_ACCU0);
DUMPREG(i, DISPC_OVL_ACCU1); DUMPREG(i, DISPC_OVL_ACCU1);
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
DUMPREG(i, DISPC_OVL_BA0_UV); DUMPREG(i, DISPC_OVL_BA0_UV);
DUMPREG(i, DISPC_OVL_BA1_UV); DUMPREG(i, DISPC_OVL_BA1_UV);
DUMPREG(i, DISPC_OVL_FIR2); DUMPREG(i, DISPC_OVL_FIR2);
DUMPREG(i, DISPC_OVL_ACCU2_0); DUMPREG(i, DISPC_OVL_ACCU2_0);
DUMPREG(i, DISPC_OVL_ACCU2_1); DUMPREG(i, DISPC_OVL_ACCU2_1);
} }
if (dss_has_feature(FEAT_ATTR2)) if (dispc_has_feature(FEAT_ATTR2))
DUMPREG(i, DISPC_OVL_ATTRIBUTES2); DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
} }
...@@ -3349,7 +3432,7 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3349,7 +3432,7 @@ static void dispc_dump_regs(struct seq_file *s)
/* Video pipeline coefficient registers */ /* Video pipeline coefficient registers */
/* start from OMAP_DSS_VIDEO1 */ /* start from OMAP_DSS_VIDEO1 */
for (i = 1; i < dss_feat_get_num_ovls(); i++) { for (i = 1; i < dispc_get_num_ovls(); i++) {
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
DUMPREG(i, DISPC_OVL_FIR_COEF_H, j); DUMPREG(i, DISPC_OVL_FIR_COEF_H, j);
...@@ -3359,12 +3442,12 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3359,12 +3442,12 @@ static void dispc_dump_regs(struct seq_file *s)
for (j = 0; j < 5; j++) for (j = 0; j < 5; j++)
DUMPREG(i, DISPC_OVL_CONV_COEF, j); DUMPREG(i, DISPC_OVL_CONV_COEF, j);
if (dss_has_feature(FEAT_FIR_COEF_V)) { if (dispc_has_feature(FEAT_FIR_COEF_V)) {
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
DUMPREG(i, DISPC_OVL_FIR_COEF_V, j); DUMPREG(i, DISPC_OVL_FIR_COEF_V, j);
} }
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j); DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j);
...@@ -3397,7 +3480,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, ...@@ -3397,7 +3480,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
return 0; return 0;
} }
bool dispc_div_calc(unsigned long dispc, bool dispc_div_calc(unsigned long dispc_freq,
unsigned long pck_min, unsigned long pck_max, unsigned long pck_min, unsigned long pck_max,
dispc_div_calc_func func, void *data) dispc_div_calc_func func, void *data)
{ {
...@@ -3415,19 +3498,19 @@ bool dispc_div_calc(unsigned long dispc, ...@@ -3415,19 +3498,19 @@ bool dispc_div_calc(unsigned long dispc,
min_fck_per_pck = 0; min_fck_per_pck = 0;
#endif #endif
pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); pckd_hw_min = dispc.feat->min_pcd;
pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); pckd_hw_max = 255;
lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); lck_max = dss_get_max_fck_rate();
pck_min = pck_min ? pck_min : 1; pck_min = pck_min ? pck_min : 1;
pck_max = pck_max ? pck_max : ULONG_MAX; pck_max = pck_max ? pck_max : ULONG_MAX;
lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul); lckd_start = max(DIV_ROUND_UP(dispc_freq, lck_max), 1ul);
lckd_stop = min(dispc / pck_min, 255ul); lckd_stop = min(dispc_freq / pck_min, 255ul);
for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) { for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
lck = dispc / lckd; lck = dispc_freq / lckd;
pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min); pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
pckd_stop = min(lck / pck_min, pckd_hw_max); pckd_stop = min(lck / pck_min, pckd_hw_max);
...@@ -3441,7 +3524,7 @@ bool dispc_div_calc(unsigned long dispc, ...@@ -3441,7 +3524,7 @@ bool dispc_div_calc(unsigned long dispc,
* also. Thus we need to use the calculated lck. For * also. Thus we need to use the calculated lck. For
* OMAP4+ the DISPC fclk is a separate clock. * OMAP4+ the DISPC fclk is a separate clock.
*/ */
if (dss_has_feature(FEAT_CORE_CLK_DIV)) if (dispc_has_feature(FEAT_CORE_CLK_DIV))
fck = dispc_core_clk_rate(); fck = dispc_core_clk_rate();
else else
fck = lck; fck = lck;
...@@ -3556,10 +3639,10 @@ static void dispc_restore_gamma_tables(void) ...@@ -3556,10 +3639,10 @@ static void dispc_restore_gamma_tables(void)
dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_DIGIT); dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_DIGIT);
if (dss_has_feature(FEAT_MGR_LCD2)) if (dispc_has_feature(FEAT_MGR_LCD2))
dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD2); dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD2);
if (dss_has_feature(FEAT_MGR_LCD3)) if (dispc_has_feature(FEAT_MGR_LCD3))
dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD3); dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD3);
} }
...@@ -3627,11 +3710,11 @@ static int dispc_init_gamma_tables(void) ...@@ -3627,11 +3710,11 @@ static int dispc_init_gamma_tables(void)
u32 *gt; u32 *gt;
if (channel == OMAP_DSS_CHANNEL_LCD2 && if (channel == OMAP_DSS_CHANNEL_LCD2 &&
!dss_has_feature(FEAT_MGR_LCD2)) !dispc_has_feature(FEAT_MGR_LCD2))
continue; continue;
if (channel == OMAP_DSS_CHANNEL_LCD3 && if (channel == OMAP_DSS_CHANNEL_LCD3 &&
!dss_has_feature(FEAT_MGR_LCD3)) !dispc_has_feature(FEAT_MGR_LCD3))
continue; continue;
gt = devm_kmalloc_array(&dispc.pdev->dev, gdesc->len, gt = devm_kmalloc_array(&dispc.pdev->dev, gdesc->len,
...@@ -3651,7 +3734,7 @@ static void _omap_dispc_initial_config(void) ...@@ -3651,7 +3734,7 @@ static void _omap_dispc_initial_config(void)
u32 l; u32 l;
/* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
if (dss_has_feature(FEAT_CORE_CLK_DIV)) { if (dispc_has_feature(FEAT_CORE_CLK_DIV)) {
l = dispc_read_reg(DISPC_DIVISOR); l = dispc_read_reg(DISPC_DIVISOR);
/* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
l = FLD_MOD(l, 1, 0, 0); l = FLD_MOD(l, 1, 0, 0);
...@@ -3669,7 +3752,7 @@ static void _omap_dispc_initial_config(void) ...@@ -3669,7 +3752,7 @@ static void _omap_dispc_initial_config(void)
* func-clock auto-gating. For newer versions * func-clock auto-gating. For newer versions
* (dispc.feat->has_gamma_table) this enables tv-out gamma tables. * (dispc.feat->has_gamma_table) this enables tv-out gamma tables.
*/ */
if (dss_has_feature(FEAT_FUNCGATED) || dispc.feat->has_gamma_table) if (dispc_has_feature(FEAT_FUNCGATED) || dispc.feat->has_gamma_table)
REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
dispc_setup_color_conv_coef(); dispc_setup_color_conv_coef();
...@@ -3685,10 +3768,272 @@ static void _omap_dispc_initial_config(void) ...@@ -3685,10 +3768,272 @@ static void _omap_dispc_initial_config(void)
if (dispc.feat->mstandby_workaround) if (dispc.feat->mstandby_workaround)
REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0); REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0);
if (dss_has_feature(FEAT_MFLAG)) if (dispc_has_feature(FEAT_MFLAG))
dispc_init_mflag(); dispc_init_mflag();
} }
static const enum dispc_feature_id omap2_dispc_features_list[] = {
FEAT_LCDENABLEPOL,
FEAT_LCDENABLESIGNAL,
FEAT_PCKFREEENABLE,
FEAT_FUNCGATED,
FEAT_ROWREPEATENABLE,
FEAT_RESIZECONF,
};
static const enum dispc_feature_id omap3_dispc_features_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,
FEAT_OMAP3_DSI_FIFO_BUG,
};
static const enum dispc_feature_id am43xx_dispc_features_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 dispc_feature_id omap4_dispc_features_list[] = {
FEAT_MGR_LCD2,
FEAT_CORE_CLK_DIV,
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 dispc_feature_id omap5_dispc_features_list[] = {
FEAT_MGR_LCD2,
FEAT_MGR_LCD3,
FEAT_CORE_CLK_DIV,
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_MFLAG,
};
static const struct dss_reg_field omap2_dispc_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 },
};
static const struct dss_reg_field omap3_dispc_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 },
};
static const struct dss_reg_field omap4_dispc_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 },
};
static const enum omap_overlay_caps omap2_dispc_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_dispc_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_dispc_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_dispc_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,
};
#define COLOR_ARRAY(arr...) (const u32[]) { arr, 0 }
static const u32 *omap2_dispc_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_dispc_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_dispc_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 struct dispc_features omap24xx_dispc_feats = { static const struct dispc_features omap24xx_dispc_feats = {
.sw_start = 5, .sw_start = 5,
.fp_start = 15, .fp_start = 15,
...@@ -3701,9 +4046,26 @@ static const struct dispc_features omap24xx_dispc_feats = { ...@@ -3701,9 +4046,26 @@ static const struct dispc_features omap24xx_dispc_feats = {
.mgr_width_max = 2048, .mgr_width_max = 2048,
.mgr_height_max = 2048, .mgr_height_max = 2048,
.max_lcd_pclk = 66500000, .max_lcd_pclk = 66500000,
.max_downscale = 2,
/*
* Assume the line width buffer to be 768 pixels as OMAP2 DISPC scaler
* cannot scale an image width larger than 768.
*/
.max_line_width = 768,
.min_pcd = 2,
.calc_scaling = dispc_ovl_calc_scaling_24xx, .calc_scaling = dispc_ovl_calc_scaling_24xx,
.calc_core_clk = calc_core_clk_24xx, .calc_core_clk = calc_core_clk_24xx,
.num_fifos = 3, .num_fifos = 3,
.features = omap2_dispc_features_list,
.num_features = ARRAY_SIZE(omap2_dispc_features_list),
.reg_fields = omap2_dispc_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap2_dispc_reg_fields),
.overlay_caps = omap2_dispc_overlay_caps,
.supported_color_modes = omap2_dispc_supported_color_modes,
.num_mgrs = 2,
.num_ovls = 3,
.buffer_size_unit = 1,
.burst_size_unit = 8,
.no_framedone_tv = true, .no_framedone_tv = true,
.set_max_preload = false, .set_max_preload = false,
.last_pixel_inc_missing = true, .last_pixel_inc_missing = true,
...@@ -3722,9 +4084,22 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = { ...@@ -3722,9 +4084,22 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = {
.mgr_height_max = 2048, .mgr_height_max = 2048,
.max_lcd_pclk = 173000000, .max_lcd_pclk = 173000000,
.max_tv_pclk = 59000000, .max_tv_pclk = 59000000,
.max_downscale = 4,
.max_line_width = 1024,
.min_pcd = 1,
.calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_scaling = dispc_ovl_calc_scaling_34xx,
.calc_core_clk = calc_core_clk_34xx, .calc_core_clk = calc_core_clk_34xx,
.num_fifos = 3, .num_fifos = 3,
.features = omap3_dispc_features_list,
.num_features = ARRAY_SIZE(omap3_dispc_features_list),
.reg_fields = omap3_dispc_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields),
.overlay_caps = omap3430_dispc_overlay_caps,
.supported_color_modes = omap3_dispc_supported_color_modes,
.num_mgrs = 2,
.num_ovls = 3,
.buffer_size_unit = 1,
.burst_size_unit = 8,
.no_framedone_tv = true, .no_framedone_tv = true,
.set_max_preload = false, .set_max_preload = false,
.last_pixel_inc_missing = true, .last_pixel_inc_missing = true,
...@@ -3743,9 +4118,90 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = { ...@@ -3743,9 +4118,90 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = {
.mgr_height_max = 2048, .mgr_height_max = 2048,
.max_lcd_pclk = 173000000, .max_lcd_pclk = 173000000,
.max_tv_pclk = 59000000, .max_tv_pclk = 59000000,
.max_downscale = 4,
.max_line_width = 1024,
.min_pcd = 1,
.calc_scaling = dispc_ovl_calc_scaling_34xx,
.calc_core_clk = calc_core_clk_34xx,
.num_fifos = 3,
.features = omap3_dispc_features_list,
.num_features = ARRAY_SIZE(omap3_dispc_features_list),
.reg_fields = omap3_dispc_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields),
.overlay_caps = omap3430_dispc_overlay_caps,
.supported_color_modes = omap3_dispc_supported_color_modes,
.num_mgrs = 2,
.num_ovls = 3,
.buffer_size_unit = 1,
.burst_size_unit = 8,
.no_framedone_tv = true,
.set_max_preload = false,
.last_pixel_inc_missing = true,
};
static const struct dispc_features omap36xx_dispc_feats = {
.sw_start = 7,
.fp_start = 19,
.bp_start = 31,
.sw_max = 256,
.vp_max = 4095,
.hp_max = 4096,
.mgr_width_start = 10,
.mgr_height_start = 26,
.mgr_width_max = 2048,
.mgr_height_max = 2048,
.max_lcd_pclk = 173000000,
.max_tv_pclk = 59000000,
.max_downscale = 4,
.max_line_width = 1024,
.min_pcd = 1,
.calc_scaling = dispc_ovl_calc_scaling_34xx,
.calc_core_clk = calc_core_clk_34xx,
.num_fifos = 3,
.features = omap3_dispc_features_list,
.num_features = ARRAY_SIZE(omap3_dispc_features_list),
.reg_fields = omap3_dispc_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields),
.overlay_caps = omap3630_dispc_overlay_caps,
.supported_color_modes = omap3_dispc_supported_color_modes,
.num_mgrs = 2,
.num_ovls = 3,
.buffer_size_unit = 1,
.burst_size_unit = 8,
.no_framedone_tv = true,
.set_max_preload = false,
.last_pixel_inc_missing = true,
};
static const struct dispc_features am43xx_dispc_feats = {
.sw_start = 7,
.fp_start = 19,
.bp_start = 31,
.sw_max = 256,
.vp_max = 4095,
.hp_max = 4096,
.mgr_width_start = 10,
.mgr_height_start = 26,
.mgr_width_max = 2048,
.mgr_height_max = 2048,
.max_lcd_pclk = 173000000,
.max_tv_pclk = 59000000,
.max_downscale = 4,
.max_line_width = 1024,
.min_pcd = 1,
.calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_scaling = dispc_ovl_calc_scaling_34xx,
.calc_core_clk = calc_core_clk_34xx, .calc_core_clk = calc_core_clk_34xx,
.num_fifos = 3, .num_fifos = 3,
.features = am43xx_dispc_features_list,
.num_features = ARRAY_SIZE(am43xx_dispc_features_list),
.reg_fields = omap3_dispc_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields),
.overlay_caps = omap3430_dispc_overlay_caps,
.supported_color_modes = omap3_dispc_supported_color_modes,
.num_mgrs = 1,
.num_ovls = 3,
.buffer_size_unit = 1,
.burst_size_unit = 8,
.no_framedone_tv = true, .no_framedone_tv = true,
.set_max_preload = false, .set_max_preload = false,
.last_pixel_inc_missing = true, .last_pixel_inc_missing = true,
...@@ -3764,9 +4220,22 @@ static const struct dispc_features omap44xx_dispc_feats = { ...@@ -3764,9 +4220,22 @@ static const struct dispc_features omap44xx_dispc_feats = {
.mgr_height_max = 2048, .mgr_height_max = 2048,
.max_lcd_pclk = 170000000, .max_lcd_pclk = 170000000,
.max_tv_pclk = 185625000, .max_tv_pclk = 185625000,
.max_downscale = 4,
.max_line_width = 2048,
.min_pcd = 1,
.calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_scaling = dispc_ovl_calc_scaling_44xx,
.calc_core_clk = calc_core_clk_44xx, .calc_core_clk = calc_core_clk_44xx,
.num_fifos = 5, .num_fifos = 5,
.features = omap4_dispc_features_list,
.num_features = ARRAY_SIZE(omap4_dispc_features_list),
.reg_fields = omap4_dispc_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap4_dispc_reg_fields),
.overlay_caps = omap4_dispc_overlay_caps,
.supported_color_modes = omap4_dispc_supported_color_modes,
.num_mgrs = 3,
.num_ovls = 4,
.buffer_size_unit = 16,
.burst_size_unit = 16,
.gfx_fifo_workaround = true, .gfx_fifo_workaround = true,
.set_max_preload = true, .set_max_preload = true,
.supports_sync_align = true, .supports_sync_align = true,
...@@ -3790,9 +4259,22 @@ static const struct dispc_features omap54xx_dispc_feats = { ...@@ -3790,9 +4259,22 @@ static const struct dispc_features omap54xx_dispc_feats = {
.mgr_height_max = 4096, .mgr_height_max = 4096,
.max_lcd_pclk = 170000000, .max_lcd_pclk = 170000000,
.max_tv_pclk = 186000000, .max_tv_pclk = 186000000,
.max_downscale = 4,
.max_line_width = 2048,
.min_pcd = 1,
.calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_scaling = dispc_ovl_calc_scaling_44xx,
.calc_core_clk = calc_core_clk_44xx, .calc_core_clk = calc_core_clk_44xx,
.num_fifos = 5, .num_fifos = 5,
.features = omap5_dispc_features_list,
.num_features = ARRAY_SIZE(omap5_dispc_features_list),
.reg_fields = omap4_dispc_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap4_dispc_reg_fields),
.overlay_caps = omap4_dispc_overlay_caps,
.supported_color_modes = omap4_dispc_supported_color_modes,
.num_mgrs = 4,
.num_ovls = 4,
.buffer_size_unit = 16,
.burst_size_unit = 16,
.gfx_fifo_workaround = true, .gfx_fifo_workaround = true,
.mstandby_workaround = true, .mstandby_workaround = true,
.set_max_preload = true, .set_max_preload = true,
...@@ -3804,54 +4286,6 @@ static const struct dispc_features omap54xx_dispc_feats = { ...@@ -3804,54 +4286,6 @@ static const struct dispc_features omap54xx_dispc_feats = {
.has_gamma_i734_bug = true, .has_gamma_i734_bug = true,
}; };
static int dispc_init_features(struct platform_device *pdev)
{
const struct dispc_features *src;
struct dispc_features *dst;
dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
if (!dst) {
dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
return -ENOMEM;
}
switch (omapdss_get_version()) {
case OMAPDSS_VER_OMAP24xx:
src = &omap24xx_dispc_feats;
break;
case OMAPDSS_VER_OMAP34xx_ES1:
src = &omap34xx_rev1_0_dispc_feats;
break;
case OMAPDSS_VER_OMAP34xx_ES3:
case OMAPDSS_VER_OMAP3630:
case OMAPDSS_VER_AM35xx:
case OMAPDSS_VER_AM43xx:
src = &omap34xx_rev3_0_dispc_feats;
break;
case OMAPDSS_VER_OMAP4430_ES1:
case OMAPDSS_VER_OMAP4430_ES2:
case OMAPDSS_VER_OMAP4:
src = &omap44xx_dispc_feats;
break;
case OMAPDSS_VER_OMAP5:
case OMAPDSS_VER_DRA7xx:
src = &omap54xx_dispc_feats;
break;
default:
return -ENODEV;
}
memcpy(dst, src, sizeof(*dst));
dispc.feat = dst;
return 0;
}
static irqreturn_t dispc_irq_handler(int irq, void *arg) static irqreturn_t dispc_irq_handler(int irq, void *arg)
{ {
if (!dispc.is_enabled) if (!dispc.is_enabled)
...@@ -4083,9 +4517,28 @@ static const struct dispc_ops dispc_ops = { ...@@ -4083,9 +4517,28 @@ static const struct dispc_ops dispc_ops = {
}; };
/* DISPC HW IP initialisation */ /* DISPC HW IP initialisation */
static const struct of_device_id dispc_of_match[] = {
{ .compatible = "ti,omap2-dispc", .data = &omap24xx_dispc_feats },
{ .compatible = "ti,omap3-dispc", .data = &omap36xx_dispc_feats },
{ .compatible = "ti,omap4-dispc", .data = &omap44xx_dispc_feats },
{ .compatible = "ti,omap5-dispc", .data = &omap54xx_dispc_feats },
{ .compatible = "ti,dra7-dispc", .data = &omap54xx_dispc_feats },
{},
};
static const struct soc_device_attribute dispc_soc_devices[] = {
{ .machine = "OMAP3[45]*",
.revision = "ES[12].?", .data = &omap34xx_rev1_0_dispc_feats },
{ .machine = "OMAP3[45]*", .data = &omap34xx_rev3_0_dispc_feats },
{ .machine = "AM35*", .data = &omap34xx_rev3_0_dispc_feats },
{ .machine = "AM43*", .data = &am43xx_dispc_feats },
{ /* sentinel */ }
};
static int dispc_bind(struct device *dev, struct device *master, void *data) static int dispc_bind(struct device *dev, struct device *master, void *data)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
const struct soc_device_attribute *soc;
u32 rev; u32 rev;
int r = 0; int r = 0;
struct resource *dispc_mem; struct resource *dispc_mem;
...@@ -4095,9 +4548,15 @@ static int dispc_bind(struct device *dev, struct device *master, void *data) ...@@ -4095,9 +4548,15 @@ static int dispc_bind(struct device *dev, struct device *master, void *data)
spin_lock_init(&dispc.control_lock); spin_lock_init(&dispc.control_lock);
r = dispc_init_features(dispc.pdev); /*
if (r) * The OMAP3-based models can't be told apart using the compatible
return r; * string, use SoC device matching.
*/
soc = soc_device_match(dispc_soc_devices);
if (soc)
dispc.feat = soc->data;
else
dispc.feat = of_match_device(dispc_of_match, &pdev->dev)->data;
r = dispc_errata_i734_wa_init(); r = dispc_errata_i734_wa_init();
if (r) if (r)
...@@ -4226,15 +4685,6 @@ static const struct dev_pm_ops dispc_pm_ops = { ...@@ -4226,15 +4685,6 @@ static const struct dev_pm_ops dispc_pm_ops = {
.runtime_resume = dispc_runtime_resume, .runtime_resume = dispc_runtime_resume,
}; };
static const struct of_device_id dispc_of_match[] = {
{ .compatible = "ti,omap2-dispc", },
{ .compatible = "ti,omap3-dispc", },
{ .compatible = "ti,omap4-dispc", },
{ .compatible = "ti,omap5-dispc", },
{ .compatible = "ti,dra7-dispc", },
{},
};
static struct platform_driver omap_dispchw_driver = { static struct platform_driver omap_dispchw_driver = {
.probe = dispc_probe, .probe = dispc_probe,
.remove = dispc_remove, .remove = dispc_remove,
......
...@@ -32,13 +32,14 @@ ...@@ -32,13 +32,14 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/sys_soc.h>
#include "omapdss.h" #include "omapdss.h"
#include "dss.h" #include "dss.h"
#include "dss_features.h"
struct dpi_data { struct dpi_data {
struct platform_device *pdev; struct platform_device *pdev;
enum dss_model dss_model;
struct regulator *vdds_dsi_reg; struct regulator *vdds_dsi_reg;
enum dss_clk_source clk_src; enum dss_clk_source clk_src;
...@@ -99,25 +100,21 @@ static enum dss_clk_source dpi_get_clk_src_dra7xx(enum omap_channel channel) ...@@ -99,25 +100,21 @@ static enum dss_clk_source dpi_get_clk_src_dra7xx(enum omap_channel channel)
return DSS_CLK_SRC_FCK; 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 * 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 * would also be used for DISPC fclk. Meaning, when the DPI output is
* disabled, DISPC clock will be disabled, and TV out will stop. * disabled, DISPC clock will be disabled, and TV out will stop.
*/ */
switch (omapdss_get_version()) { switch (dpi->dss_model) {
case OMAPDSS_VER_OMAP24xx: case DSS_MODEL_OMAP2:
case OMAPDSS_VER_OMAP34xx_ES1: case DSS_MODEL_OMAP3:
case OMAPDSS_VER_OMAP34xx_ES3:
case OMAPDSS_VER_OMAP3630:
case OMAPDSS_VER_AM35xx:
case OMAPDSS_VER_AM43xx:
return DSS_CLK_SRC_FCK; return DSS_CLK_SRC_FCK;
case OMAPDSS_VER_OMAP4430_ES1: case DSS_MODEL_OMAP4:
case OMAPDSS_VER_OMAP4430_ES2:
case OMAPDSS_VER_OMAP4:
switch (channel) { switch (channel) {
case OMAP_DSS_CHANNEL_LCD: case OMAP_DSS_CHANNEL_LCD:
return DSS_CLK_SRC_PLL1_1; return DSS_CLK_SRC_PLL1_1;
...@@ -127,7 +124,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel) ...@@ -127,7 +124,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel)
return DSS_CLK_SRC_FCK; return DSS_CLK_SRC_FCK;
} }
case OMAPDSS_VER_OMAP5: case DSS_MODEL_OMAP5:
switch (channel) { switch (channel) {
case OMAP_DSS_CHANNEL_LCD: case OMAP_DSS_CHANNEL_LCD:
return DSS_CLK_SRC_PLL1_1; return DSS_CLK_SRC_PLL1_1;
...@@ -138,7 +135,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel) ...@@ -138,7 +135,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel)
return DSS_CLK_SRC_FCK; return DSS_CLK_SRC_FCK;
} }
case OMAPDSS_VER_DRA7xx: case DSS_MODEL_DRA7:
return dpi_get_clk_src_dra7xx(channel); return dpi_get_clk_src_dra7xx(channel);
default: default:
...@@ -213,7 +210,7 @@ static bool dpi_calc_pll_cb(int n, int m, unsigned long fint, ...@@ -213,7 +210,7 @@ static bool dpi_calc_pll_cb(int n, int m, unsigned long fint,
ctx->pll_cinfo.clkdco = clkdco; ctx->pll_cinfo.clkdco = clkdco;
return dss_pll_hsdiv_calc_a(ctx->pll, 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); dpi_calc_hsdiv_cb, ctx);
} }
...@@ -403,19 +400,13 @@ static int dpi_display_enable(struct omap_dss_device *dssdev) ...@@ -403,19 +400,13 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
mutex_lock(&dpi->lock); 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) { if (!out->dispc_channel_connected) {
DSSERR("failed to enable display: no output/manager\n"); DSSERR("failed to enable display: no output/manager\n");
r = -ENODEV; r = -ENODEV;
goto err_no_out_mgr; 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); r = regulator_enable(dpi->vdds_dsi_reg);
if (r) if (r)
goto err_reg_enable; goto err_reg_enable;
...@@ -459,11 +450,10 @@ static int dpi_display_enable(struct omap_dss_device *dssdev) ...@@ -459,11 +450,10 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
err_src_sel: err_src_sel:
dispc_runtime_put(); dispc_runtime_put();
err_get_dispc: err_get_dispc:
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) if (dpi->vdds_dsi_reg)
regulator_disable(dpi->vdds_dsi_reg); regulator_disable(dpi->vdds_dsi_reg);
err_reg_enable: err_reg_enable:
err_no_out_mgr: err_no_out_mgr:
err_no_reg:
mutex_unlock(&dpi->lock); mutex_unlock(&dpi->lock);
return r; return r;
} }
...@@ -484,7 +474,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev) ...@@ -484,7 +474,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
dispc_runtime_put(); dispc_runtime_put();
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) if (dpi->vdds_dsi_reg)
regulator_disable(dpi->vdds_dsi_reg); regulator_disable(dpi->vdds_dsi_reg);
mutex_unlock(&dpi->lock); mutex_unlock(&dpi->lock);
...@@ -575,11 +565,21 @@ static int dpi_verify_pll(struct dss_pll *pll) ...@@ -575,11 +565,21 @@ static int dpi_verify_pll(struct dss_pll *pll)
return 0; 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) static int dpi_init_regulator(struct dpi_data *dpi)
{ {
struct regulator *vdds_dsi; 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; return 0;
if (dpi->vdds_dsi_reg) if (dpi->vdds_dsi_reg)
...@@ -604,7 +604,7 @@ static void dpi_init_pll(struct dpi_data *dpi) ...@@ -604,7 +604,7 @@ static void dpi_init_pll(struct dpi_data *dpi)
if (dpi->pll) if (dpi->pll)
return; 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); pll = dss_pll_find_by_src(dpi->clk_src);
if (!pll) if (!pll)
...@@ -624,18 +624,14 @@ static void dpi_init_pll(struct dpi_data *dpi) ...@@ -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 * the channel in some more dynamic manner, or get the channel as a user
* parameter. * 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()) { switch (dpi->dss_model) {
case OMAPDSS_VER_OMAP24xx: case DSS_MODEL_OMAP2:
case OMAPDSS_VER_OMAP34xx_ES1: case DSS_MODEL_OMAP3:
case OMAPDSS_VER_OMAP34xx_ES3:
case OMAPDSS_VER_OMAP3630:
case OMAPDSS_VER_AM35xx:
case OMAPDSS_VER_AM43xx:
return OMAP_DSS_CHANNEL_LCD; return OMAP_DSS_CHANNEL_LCD;
case OMAPDSS_VER_DRA7xx: case DSS_MODEL_DRA7:
switch (port_num) { switch (port_num) {
case 2: case 2:
return OMAP_DSS_CHANNEL_LCD3; return OMAP_DSS_CHANNEL_LCD3;
...@@ -646,12 +642,10 @@ static enum omap_channel dpi_get_channel(int port_num) ...@@ -646,12 +642,10 @@ static enum omap_channel dpi_get_channel(int port_num)
return OMAP_DSS_CHANNEL_LCD; return OMAP_DSS_CHANNEL_LCD;
} }
case OMAPDSS_VER_OMAP4430_ES1: case DSS_MODEL_OMAP4:
case OMAPDSS_VER_OMAP4430_ES2:
case OMAPDSS_VER_OMAP4:
return OMAP_DSS_CHANNEL_LCD2; return OMAP_DSS_CHANNEL_LCD2;
case OMAPDSS_VER_OMAP5: case DSS_MODEL_OMAP5:
return OMAP_DSS_CHANNEL_LCD3; return OMAP_DSS_CHANNEL_LCD3;
default: default:
...@@ -716,10 +710,8 @@ static const struct omapdss_dpi_ops dpi_ops = { ...@@ -716,10 +710,8 @@ static const struct omapdss_dpi_ops dpi_ops = {
.get_timings = dpi_get_timings, .get_timings = dpi_get_timings,
}; };
static void dpi_init_output_port(struct platform_device *pdev, static void dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
struct device_node *port)
{ {
struct dpi_data *dpi = port->data;
struct omap_dss_device *out = &dpi->output; struct omap_dss_device *out = &dpi->output;
int r; int r;
u32 port_num; u32 port_num;
...@@ -741,10 +733,10 @@ static void dpi_init_output_port(struct platform_device *pdev, ...@@ -741,10 +733,10 @@ static void dpi_init_output_port(struct platform_device *pdev,
break; break;
} }
out->dev = &pdev->dev; out->dev = &dpi->pdev->dev;
out->id = OMAP_DSS_OUTPUT_DPI; out->id = OMAP_DSS_OUTPUT_DPI;
out->output_type = OMAP_DISPLAY_TYPE_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->port_num = port_num;
out->ops.dpi = &dpi_ops; out->ops.dpi = &dpi_ops;
out->owner = THIS_MODULE; out->owner = THIS_MODULE;
...@@ -760,7 +752,8 @@ static void dpi_uninit_output_port(struct device_node *port) ...@@ -760,7 +752,8 @@ static void dpi_uninit_output_port(struct device_node *port)
omapdss_unregister_output(out); 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 dpi_data *dpi;
struct device_node *ep; struct device_node *ep;
...@@ -786,11 +779,12 @@ int dpi_init_port(struct platform_device *pdev, struct device_node *port) ...@@ -786,11 +779,12 @@ int dpi_init_port(struct platform_device *pdev, struct device_node *port)
of_node_put(ep); of_node_put(ep);
dpi->pdev = pdev; dpi->pdev = pdev;
dpi->dss_model = dss_model;
port->data = dpi; port->data = dpi;
mutex_init(&dpi->lock); mutex_init(&dpi->lock);
dpi_init_output_port(pdev, port); dpi_init_output_port(dpi, port);
dpi->port_initialized = true; dpi->port_initialized = true;
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#define DSS_SUBSYS_NAME "DSI" #define DSS_SUBSYS_NAME "DSI"
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -42,12 +44,12 @@ ...@@ -42,12 +44,12 @@
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/sys_soc.h>
#include <video/mipi_display.h> #include <video/mipi_display.h>
#include "omapdss.h" #include "omapdss.h"
#include "dss.h" #include "dss.h"
#include "dss_features.h"
#define DSI_CATCH_MISSING_TE #define DSI_CATCH_MISSING_TE
...@@ -228,6 +230,12 @@ static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); ...@@ -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_ISRS 2
#define DSI_MAX_NR_LANES 5 #define DSI_MAX_NR_LANES 5
enum dsi_model {
DSI_MODEL_OMAP3,
DSI_MODEL_OMAP4,
DSI_MODEL_OMAP5,
};
enum dsi_lane_function { enum dsi_lane_function {
DSI_LANE_UNUSED = 0, DSI_LANE_UNUSED = 0,
DSI_LANE_CLK, DSI_LANE_CLK,
...@@ -299,12 +307,36 @@ struct dsi_lp_clock_info { ...@@ -299,12 +307,36 @@ struct dsi_lp_clock_info {
u16 lp_clk_div; 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 dsi_data {
struct platform_device *pdev; struct platform_device *pdev;
void __iomem *proto_base; void __iomem *proto_base;
void __iomem *phy_base; void __iomem *phy_base;
void __iomem *pll_base; void __iomem *pll_base;
const struct dsi_of_data *data;
int module_id; int module_id;
int irq; int irq;
...@@ -312,6 +344,7 @@ struct dsi_data { ...@@ -312,6 +344,7 @@ struct dsi_data {
bool is_enabled; bool is_enabled;
struct clk *dss_clk; struct clk *dss_clk;
struct regmap *syscon;
struct dispc_clock_info user_dispc_cinfo; struct dispc_clock_info user_dispc_cinfo;
struct dss_pll_clock_info user_dsi_cinfo; struct dss_pll_clock_info user_dsi_cinfo;
...@@ -397,13 +430,6 @@ struct dsi_packet_sent_handler_data { ...@@ -397,13 +430,6 @@ struct dsi_packet_sent_handler_data {
struct completion *completion; 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 #ifdef DSI_PERF_MEASURE
static bool dsi_perf; static bool dsi_perf;
module_param(dsi_perf, bool, 0644); module_param(dsi_perf, bool, 0644);
...@@ -1186,6 +1212,7 @@ static int dsi_regulator_init(struct platform_device *dsidev) ...@@ -1186,6 +1212,7 @@ static int dsi_regulator_init(struct platform_device *dsidev)
static void _dsi_print_reset_status(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; u32 l;
int b0, b1, b2; int b0, b1, b2;
...@@ -1194,7 +1221,7 @@ static void _dsi_print_reset_status(struct platform_device *dsidev) ...@@ -1194,7 +1221,7 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
* I/O. */ * I/O. */
l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); 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; b0 = 28;
b1 = 27; b1 = 27;
b2 = 26; b2 = 26;
...@@ -1297,7 +1324,7 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev) ...@@ -1297,7 +1324,7 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
unsigned long dsi_fclk; unsigned long dsi_fclk;
unsigned lp_clk_div; unsigned lp_clk_div;
unsigned long lp_clk; 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; lp_clk_div = dsi->user_lp_cinfo.lp_clk_div;
...@@ -1349,10 +1376,11 @@ enum dsi_pll_power_state { ...@@ -1349,10 +1376,11 @@ enum dsi_pll_power_state {
static int dsi_pll_power(struct platform_device *dsidev, static int dsi_pll_power(struct platform_device *dsidev,
enum dsi_pll_power_state state) enum dsi_pll_power_state state)
{ {
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
int t = 0; int t = 0;
/* DSI-PLL power command 0x3 is not working */ /* DSI-PLL power command 0x3 is not working */
if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) && if ((dsi->data->quirks & DSI_QUIRK_PLL_PWR_BUG) &&
state == DSI_PLL_POWER_ON_DIV) state == DSI_PLL_POWER_ON_DIV)
state = DSI_PLL_POWER_ON_ALL; state = DSI_PLL_POWER_ON_ALL;
...@@ -1373,11 +1401,12 @@ static int dsi_pll_power(struct platform_device *dsidev, ...@@ -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; 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->mX[HSDIV_DSI] = DIV_ROUND_UP(cinfo->clkdco, max_dsi_fck);
cinfo->clkout[HSDIV_DSI] = cinfo->clkdco / cinfo->mX[HSDIV_DSI]; cinfo->clkout[HSDIV_DSI] = cinfo->clkdco / cinfo->mX[HSDIV_DSI];
...@@ -1773,13 +1802,14 @@ static int dsi_cio_power(struct platform_device *dsidev, ...@@ -1773,13 +1802,14 @@ static int dsi_cio_power(struct platform_device *dsidev,
static unsigned dsi_get_line_buf_size(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; int val;
/* line buffer on OMAP3 is 1024 x 24bits */ /* line buffer on OMAP3 is 1024 x 24bits */
/* XXX: for some reason using full buffer size causes /* XXX: for some reason using full buffer size causes
* considerable TX slowdown with update sizes that fill the * considerable TX slowdown with update sizes that fill the
* whole buffer */ * whole buffer */
if (!dss_has_feature(FEAT_DSI_GNQ)) if (!(dsi->data->quirks & DSI_QUIRK_GNQ))
return 1023 * 3; return 1023 * 3;
val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */ 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) ...@@ -1872,6 +1902,7 @@ static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
static void dsi_cio_timings(struct platform_device *dsidev) static void dsi_cio_timings(struct platform_device *dsidev)
{ {
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
u32 r; u32 r;
u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
u32 tlpx_half, tclk_trail, tclk_zero; u32 tlpx_half, tclk_trail, tclk_zero;
...@@ -1934,7 +1965,7 @@ static void dsi_cio_timings(struct platform_device *dsidev) ...@@ -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_trail, 15, 8);
r = FLD_MOD(r, tclk_zero, 7, 0); 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, 0, 21, 21); /* DCCEN = disable */
r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */ r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = 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) ...@@ -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 }; static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
const u8 *offsets; const u8 *offsets;
if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) if (dsi->data->quirks & DSI_QUIRK_REVERSE_TXCLKESC)
offsets = offsets_old; offsets = offsets_old;
else else
offsets = offsets_new; offsets = offsets_new;
...@@ -2060,6 +2091,83 @@ static unsigned dsi_get_lane_mask(struct platform_device *dsidev) ...@@ -2060,6 +2091,83 @@ static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
return mask; 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) static int dsi_cio_init(struct platform_device *dsidev)
{ {
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
...@@ -2068,7 +2176,7 @@ static int dsi_cio_init(struct platform_device *dsidev) ...@@ -2068,7 +2176,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
DSSDBG("DSI CIO init starts"); 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) if (r)
return r; return r;
...@@ -2178,7 +2286,7 @@ static int dsi_cio_init(struct platform_device *dsidev) ...@@ -2178,7 +2286,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
dsi_cio_disable_lane_override(dsidev); dsi_cio_disable_lane_override(dsidev);
err_scp_clk_dom: err_scp_clk_dom:
dsi_disable_scp_clk(dsidev); dsi_disable_scp_clk(dsidev);
dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); dsi_disable_pads(dsi);
return r; return r;
} }
...@@ -2191,7 +2299,7 @@ static void dsi_cio_uninit(struct platform_device *dsidev) ...@@ -2191,7 +2299,7 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
dsi_disable_scp_clk(dsidev); 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, 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) ...@@ -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, 7, 7); /* CS_TX_EN */
r = FLD_MOD(r, 1, 8, 8); /* ECC_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 */ 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, 3, 11, 10); /* OCP_WIDTH = 32 bit */
r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ 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, ...@@ -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); REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
/* DCS_CMD_ENABLE */ /* 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; bool enable = source == DSI_VC_SOURCE_VP;
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30); REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
} }
...@@ -3607,7 +3715,7 @@ static int dsi_proto_config(struct platform_device *dsidev) ...@@ -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, 0, 8, 8); /* VP_CLK_POL */
r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ 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 */ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
/* DCS_CMD_CODE, 1=start, 0=continue */ /* DCS_CMD_CODE, 1=start, 0=continue */
r = FLD_MOD(r, 0, 25, 25); 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, ...@@ -4450,6 +4558,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
unsigned long clkdco, void *data) unsigned long clkdco, void *data)
{ {
struct dsi_clk_calc_ctx *ctx = 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.n = n;
ctx->dsi_cinfo.m = m; ctx->dsi_cinfo.m = m;
...@@ -4457,7 +4566,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint, ...@@ -4457,7 +4566,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
ctx->dsi_cinfo.clkdco = clkdco; ctx->dsi_cinfo.clkdco = clkdco;
return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min, 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); dsi_cm_calc_hsdiv_cb, ctx);
} }
...@@ -4749,6 +4858,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint, ...@@ -4749,6 +4858,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
unsigned long clkdco, void *data) unsigned long clkdco, void *data)
{ {
struct dsi_clk_calc_ctx *ctx = 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.n = n;
ctx->dsi_cinfo.m = m; ctx->dsi_cinfo.m = m;
...@@ -4756,7 +4866,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint, ...@@ -4756,7 +4866,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
ctx->dsi_cinfo.clkdco = clkdco; ctx->dsi_cinfo.clkdco = clkdco;
return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min, 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); dsi_vm_calc_hsdiv_cb, ctx);
} }
...@@ -4827,7 +4937,7 @@ static int dsi_set_config(struct omap_dss_device *dssdev, ...@@ -4827,7 +4937,7 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
goto err; 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], r = dsi_lp_clock_calc(ctx.dsi_cinfo.clkout[HSDIV_DSI],
config->lp_clk_min, config->lp_clk_max, &dsi->user_lp_cinfo); 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, ...@@ -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 * the channel in some more dynamic manner, or get the channel as a user
* parameter. * 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()) { switch (dsi->data->model) {
case OMAPDSS_VER_OMAP24xx: case DSI_MODEL_OMAP3:
case OMAPDSS_VER_AM43xx:
DSSWARN("DSI not supported\n");
return OMAP_DSS_CHANNEL_LCD; return OMAP_DSS_CHANNEL_LCD;
case OMAPDSS_VER_OMAP34xx_ES1: case DSI_MODEL_OMAP4:
case OMAPDSS_VER_OMAP34xx_ES3: switch (dsi->module_id) {
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 0: case 0:
return OMAP_DSS_CHANNEL_LCD; return OMAP_DSS_CHANNEL_LCD;
case 1: case 1:
...@@ -4884,8 +4984,8 @@ static enum omap_channel dsi_get_channel(int module_id) ...@@ -4884,8 +4984,8 @@ static enum omap_channel dsi_get_channel(int module_id)
return OMAP_DSS_CHANNEL_LCD; return OMAP_DSS_CHANNEL_LCD;
} }
case OMAPDSS_VER_OMAP5: case DSI_MODEL_OMAP5:
switch (module_id) { switch (dsi->module_id) {
case 0: case 0:
return OMAP_DSS_CHANNEL_LCD; return OMAP_DSS_CHANNEL_LCD;
case 1: case 1:
...@@ -5065,7 +5165,7 @@ static void dsi_init_output(struct platform_device *dsidev) ...@@ -5065,7 +5165,7 @@ static void dsi_init_output(struct platform_device *dsidev)
out->output_type = OMAP_DISPLAY_TYPE_DSI; out->output_type = OMAP_DISPLAY_TYPE_DSI;
out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; 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->ops.dsi = &dsi_ops;
out->owner = THIS_MODULE; out->owner = THIS_MODULE;
...@@ -5240,29 +5340,7 @@ static int dsi_init_pll_data(struct platform_device *dsidev) ...@@ -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->id = dsi->module_id == 0 ? DSS_PLL_DSI1 : DSS_PLL_DSI2;
pll->clkin = clk; pll->clkin = clk;
pll->base = dsi->pll_base; pll->base = dsi->pll_base;
pll->hw = dsi->data->pll_hw;
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->ops = &dsi_pll_ops; pll->ops = &dsi_pll_ops;
r = dss_pll_register(pll); r = dss_pll_register(pll);
...@@ -5273,9 +5351,74 @@ static int dsi_init_pll_data(struct platform_device *dsidev) ...@@ -5273,9 +5351,74 @@ static int dsi_init_pll_data(struct platform_device *dsidev)
} }
/* DSI1 HW IP initialisation */ /* 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) static int dsi_bind(struct device *dev, struct device *master, void *data)
{ {
struct platform_device *dsidev = to_platform_device(dev); struct platform_device *dsidev = to_platform_device(dev);
const struct soc_device_attribute *soc;
const struct dsi_module_id_data *d; const struct dsi_module_id_data *d;
u32 rev; u32 rev;
int r, i; int r, i;
...@@ -5339,7 +5482,13 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) ...@@ -5339,7 +5482,13 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
return r; 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) while (d->address != 0 && d->address != dsi_mem->start)
d++; d++;
...@@ -5350,6 +5499,24 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) ...@@ -5350,6 +5499,24 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
dsi->module_id = d->id; 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 */ /* DSI VCs initialization */
for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
dsi->vc[i].source = DSI_VC_SOURCE_L4; dsi->vc[i].source = DSI_VC_SOURCE_L4;
...@@ -5375,7 +5542,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) ...@@ -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 /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
* of data to 3 by default */ * of data to 3 by default */
if (dss_has_feature(FEAT_DSI_GNQ)) if (dsi->data->quirks & DSI_QUIRK_GNQ)
/* NB_DATA_LANES */ /* NB_DATA_LANES */
dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9); dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
else else
...@@ -5495,30 +5662,6 @@ static const struct dev_pm_ops dsi_pm_ops = { ...@@ -5495,30 +5662,6 @@ static const struct dev_pm_ops dsi_pm_ops = {
.runtime_resume = dsi_runtime_resume, .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 = { static struct platform_driver omap_dsihw_driver = {
.probe = dsi_probe, .probe = dsi_probe,
.remove = dsi_remove, .remove = dsi_remove,
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define DSS_SUBSYS_NAME "DSS" #define DSS_SUBSYS_NAME "DSS"
#include <linux/debugfs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -38,14 +39,15 @@ ...@@ -38,14 +39,15 @@
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/sys_soc.h>
#include "omapdss.h" #include "omapdss.h"
#include "dss.h" #include "dss.h"
#include "dss_features.h"
#define DSS_SZ_REGS SZ_512 #define DSS_SZ_REGS SZ_512
...@@ -69,15 +71,24 @@ struct dss_reg { ...@@ -69,15 +71,24 @@ struct dss_reg {
#define REG_FLD_MOD(idx, val, start, end) \ #define REG_FLD_MOD(idx, val, start, end) \
dss_write_reg(idx, FLD_MOD(dss_read_reg(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 { struct dss_features {
enum dss_model model;
u8 fck_div_max; u8 fck_div_max;
unsigned int fck_freq_max;
u8 dss_fck_multiplier; u8 dss_fck_multiplier;
const char *parent_clk_name; const char *parent_clk_name;
const enum omap_display_type *ports; const enum omap_display_type *ports;
int num_ports; int num_ports;
int (*dpi_select_source)(int port, enum omap_channel channel); const enum omap_dss_output_id *outputs;
int (*select_lcd_source)(enum omap_channel channel, const struct dss_ops *ops;
enum dss_clk_source clk_src); struct dss_reg_field dispc_clk_switch;
bool has_lcd_clk_src;
}; };
static struct { static struct {
...@@ -139,8 +150,7 @@ static void dss_save_context(void) ...@@ -139,8 +150,7 @@ static void dss_save_context(void)
SR(CONTROL); SR(CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
OMAP_DISPLAY_TYPE_SDI) {
SR(SDI_CONTROL); SR(SDI_CONTROL);
SR(PLL_CONTROL); SR(PLL_CONTROL);
} }
...@@ -159,8 +169,7 @@ static void dss_restore_context(void) ...@@ -159,8 +169,7 @@ static void dss_restore_context(void)
RR(CONTROL); RR(CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
OMAP_DISPLAY_TYPE_SDI) {
RR(SDI_CONTROL); RR(SDI_CONTROL);
RR(PLL_CONTROL); RR(PLL_CONTROL);
} }
...@@ -390,8 +399,7 @@ static void dss_dump_regs(struct seq_file *s) ...@@ -390,8 +399,7 @@ static void dss_dump_regs(struct seq_file *s)
DUMPREG(DSS_SYSSTATUS); DUMPREG(DSS_SYSSTATUS);
DUMPREG(DSS_CONTROL); DUMPREG(DSS_CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
OMAP_DISPLAY_TYPE_SDI) {
DUMPREG(DSS_SDI_CONTROL); DUMPREG(DSS_SDI_CONTROL);
DUMPREG(DSS_PLL_CONTROL); DUMPREG(DSS_PLL_CONTROL);
DUMPREG(DSS_SDI_STATUS); DUMPREG(DSS_SDI_STATUS);
...@@ -419,14 +427,12 @@ static int dss_get_channel_index(enum omap_channel channel) ...@@ -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) static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
{ {
int b; int b;
u8 start, end;
/* /*
* We always use PRCM clock as the DISPC func clock, except on DSS3, * We always use PRCM clock as the DISPC func clock, except on DSS3,
* where we don't have separate DISPC and LCD clock sources. * where we don't have separate DISPC and LCD clock sources.
*/ */
if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) && if (WARN_ON(dss.feat->has_lcd_clk_src && clk_src != DSS_CLK_SRC_FCK))
clk_src != DSS_CLK_SRC_FCK))
return; return;
switch (clk_src) { switch (clk_src) {
...@@ -444,9 +450,9 @@ static void dss_select_dispc_clk_source(enum dss_clk_source clk_src) ...@@ -444,9 +450,9 @@ static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
return; return;
} }
dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); REG_FLD_MOD(DSS_CONTROL, b, /* DISPC_CLK_SWITCH */
dss.feat->dispc_clk_switch.start,
REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */ dss.feat->dispc_clk_switch.end);
dss.dispc_clk_source = clk_src; dss.dispc_clk_source = clk_src;
} }
...@@ -570,13 +576,13 @@ void dss_select_lcd_clk_source(enum omap_channel channel, ...@@ -570,13 +576,13 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
int idx = dss_get_channel_index(channel); int idx = dss_get_channel_index(channel);
int r; 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_select_dispc_clk_source(clk_src);
dss.lcd_clk_source[idx] = clk_src; dss.lcd_clk_source[idx] = clk_src;
return; return;
} }
r = dss.feat->select_lcd_source(channel, clk_src); r = dss.feat->ops->select_lcd_source(channel, clk_src);
if (r) if (r)
return; return;
...@@ -595,7 +601,7 @@ enum dss_clk_source dss_get_dsi_clk_source(int dsi_module) ...@@ -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) 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); int idx = dss_get_channel_index(channel);
return dss.lcd_clk_source[idx]; return dss.lcd_clk_source[idx];
} else { } else {
...@@ -615,7 +621,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min, ...@@ -615,7 +621,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
unsigned long prate; unsigned long prate;
unsigned m; 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) { if (dss.parent_clk == NULL) {
unsigned pckd; unsigned pckd;
...@@ -673,6 +679,16 @@ unsigned long dss_get_dispc_clk_rate(void) ...@@ -673,6 +679,16 @@ unsigned long dss_get_dispc_clk_rate(void)
return dss.dss_clk_rate; 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) static int dss_setup_default_clock(void)
{ {
unsigned long max_dss_fck, prate; unsigned long max_dss_fck, prate;
...@@ -680,7 +696,7 @@ static int dss_setup_default_clock(void) ...@@ -680,7 +696,7 @@ static int dss_setup_default_clock(void)
unsigned fck_div; unsigned fck_div;
int r; 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) { if (dss.parent_clk == NULL) {
fck = clk_round_rate(dss.dss_clk, max_dss_fck); fck = clk_round_rate(dss.dss_clk, max_dss_fck);
...@@ -721,27 +737,29 @@ void dss_set_dac_pwrdn_bgz(bool enable) ...@@ -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) void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
{ {
enum omap_display_type dp; enum omap_dss_output_id outputs;
dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT];
/* Complain about invalid selections */ /* Complain about invalid selections */
WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC)); WARN_ON((src == DSS_VENC_TV_CLK) && !(outputs & OMAP_DSS_OUTPUT_VENC));
WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI)); WARN_ON((src == DSS_HDMI_M_PCLK) && !(outputs & OMAP_DSS_OUTPUT_HDMI));
/* Select only if we have options */ /* 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 */ 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 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); outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT];
if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) if ((outputs & OMAP_DSS_OUTPUT_HDMI) == 0)
return DSS_VENC_TV_CLK; 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 DSS_HDMI_M_PCLK;
return REG_GET(DSS_CONTROL, 15, 15); return REG_GET(DSS_CONTROL, 15, 15);
...@@ -823,7 +841,7 @@ static int dss_dpi_select_source_dra7xx(int port, enum omap_channel channel) ...@@ -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) 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) static int dss_get_clocks(void)
...@@ -882,7 +900,7 @@ void dss_runtime_put(void) ...@@ -882,7 +900,7 @@ void dss_runtime_put(void)
/* DEBUGFS */ /* DEBUGFS */
#if defined(CONFIG_OMAP2_DSS_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); dss_dump_clocks(s);
dispc_dump_clocks(s); dispc_dump_clocks(s);
...@@ -890,8 +908,88 @@ void dss_debug_dump_clocks(struct seq_file *s) ...@@ -890,8 +908,88 @@ void dss_debug_dump_clocks(struct seq_file *s)
dsi_dump_clocks(s); dsi_dump_clocks(s);
#endif #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[] = { static const enum omap_display_type omap2plus_ports[] = {
OMAP_DISPLAY_TYPE_DPI, OMAP_DISPLAY_TYPE_DPI,
...@@ -908,130 +1006,168 @@ static const enum omap_display_type dra7xx_ports[] = { ...@@ -908,130 +1006,168 @@ static const enum omap_display_type dra7xx_ports[] = {
OMAP_DISPLAY_TYPE_DPI, 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 = { 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 * 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. * from 1 to 6 has no gaps, so let's use that as a max.
*/ */
.fck_div_max = 6, .fck_div_max = 6,
.fck_freq_max = 133000000,
.dss_fck_multiplier = 2, .dss_fck_multiplier = 2,
.parent_clk_name = "core_ck", .parent_clk_name = "core_ck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(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 = { static const struct dss_features omap34xx_dss_feats = {
.model = DSS_MODEL_OMAP3,
.fck_div_max = 16, .fck_div_max = 16,
.fck_freq_max = 173000000,
.dss_fck_multiplier = 2, .dss_fck_multiplier = 2,
.parent_clk_name = "dpll4_ck", .parent_clk_name = "dpll4_ck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
.ports = omap34xx_ports, .ports = omap34xx_ports,
.outputs = omap3430_dss_supported_outputs,
.num_ports = ARRAY_SIZE(omap34xx_ports), .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 = { static const struct dss_features omap3630_dss_feats = {
.model = DSS_MODEL_OMAP3,
.fck_div_max = 32, .fck_div_max = 32,
.fck_freq_max = 173000000,
.dss_fck_multiplier = 1, .dss_fck_multiplier = 1,
.parent_clk_name = "dpll4_ck", .parent_clk_name = "dpll4_ck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(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 = { static const struct dss_features omap44xx_dss_feats = {
.model = DSS_MODEL_OMAP4,
.fck_div_max = 32, .fck_div_max = 32,
.fck_freq_max = 186000000,
.dss_fck_multiplier = 1, .dss_fck_multiplier = 1,
.parent_clk_name = "dpll_per_x2_ck", .parent_clk_name = "dpll_per_x2_ck",
.dpi_select_source = &dss_dpi_select_source_omap4,
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(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 = { static const struct dss_features omap54xx_dss_feats = {
.model = DSS_MODEL_OMAP5,
.fck_div_max = 64, .fck_div_max = 64,
.fck_freq_max = 209250000,
.dss_fck_multiplier = 1, .dss_fck_multiplier = 1,
.parent_clk_name = "dpll_per_x2_ck", .parent_clk_name = "dpll_per_x2_ck",
.dpi_select_source = &dss_dpi_select_source_omap5,
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(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 = { static const struct dss_features am43xx_dss_feats = {
.model = DSS_MODEL_OMAP3,
.fck_div_max = 0, .fck_div_max = 0,
.fck_freq_max = 200000000,
.dss_fck_multiplier = 0, .dss_fck_multiplier = 0,
.parent_clk_name = NULL, .parent_clk_name = NULL,
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(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 = { static const struct dss_features dra7xx_dss_feats = {
.model = DSS_MODEL_DRA7,
.fck_div_max = 64, .fck_div_max = 64,
.fck_freq_max = 209250000,
.dss_fck_multiplier = 1, .dss_fck_multiplier = 1,
.parent_clk_name = "dpll_per_x2_ck", .parent_clk_name = "dpll_per_x2_ck",
.dpi_select_source = &dss_dpi_select_source_dra7xx,
.ports = dra7xx_ports, .ports = dra7xx_ports,
.num_ports = ARRAY_SIZE(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) static int dss_init_ports(struct platform_device *pdev)
{ {
struct device_node *parent = pdev->dev.of_node; struct device_node *parent = pdev->dev.of_node;
...@@ -1045,7 +1181,7 @@ static int dss_init_ports(struct platform_device *pdev) ...@@ -1045,7 +1181,7 @@ static int dss_init_ports(struct platform_device *pdev)
switch (dss.feat->ports[i]) { switch (dss.feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI: case OMAP_DISPLAY_TYPE_DPI:
dpi_init_port(pdev, port); dpi_init_port(pdev, port, dss.feat->model);
break; break;
case OMAP_DISPLAY_TYPE_SDI: case OMAP_DISPLAY_TYPE_SDI:
sdi_init_port(pdev, port); sdi_init_port(pdev, port);
...@@ -1144,6 +1280,23 @@ static int dss_video_pll_probe(struct platform_device *pdev) ...@@ -1144,6 +1280,23 @@ static int dss_video_pll_probe(struct platform_device *pdev)
} }
/* DSS HW IP initialisation */ /* 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) static int dss_bind(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
...@@ -1151,12 +1304,6 @@ static int dss_bind(struct device *dev) ...@@ -1151,12 +1304,6 @@ static int dss_bind(struct device *dev)
u32 rev; u32 rev;
int r; 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_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
dss.base = devm_ioremap_resource(&pdev->dev, dss_mem); dss.base = devm_ioremap_resource(&pdev->dev, dss_mem);
if (IS_ERR(dss.base)) if (IS_ERR(dss.base))
...@@ -1288,15 +1435,34 @@ static int dss_add_child_component(struct device *dev, void *data) ...@@ -1288,15 +1435,34 @@ static int dss_add_child_component(struct device *dev, void *data)
static int dss_probe(struct platform_device *pdev) static int dss_probe(struct platform_device *pdev)
{ {
const struct soc_device_attribute *soc;
struct component_match *match = NULL; struct component_match *match = NULL;
int r; 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 */ /* add all the child devices as components */
device_for_each_child(&pdev->dev, &match, dss_add_child_component); device_for_each_child(&pdev->dev, &match, dss_add_child_component);
r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match); r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
if (r) if (r) {
dss_uninitialize_debugfs();
return r; return r;
}
return 0; return 0;
} }
...@@ -1304,9 +1470,27 @@ static int dss_probe(struct platform_device *pdev) ...@@ -1304,9 +1470,27 @@ static int dss_probe(struct platform_device *pdev)
static int dss_remove(struct platform_device *pdev) static int dss_remove(struct platform_device *pdev)
{ {
component_master_del(&pdev->dev, &dss_component_ops); component_master_del(&pdev->dev, &dss_component_ops);
dss_uninitialize_debugfs();
return 0; 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) static int dss_runtime_suspend(struct device *dev)
{ {
dss_save_context(); dss_save_context();
...@@ -1343,20 +1527,10 @@ static const struct dev_pm_ops dss_pm_ops = { ...@@ -1343,20 +1527,10 @@ static const struct dev_pm_ops dss_pm_ops = {
.runtime_resume = dss_runtime_resume, .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 = { static struct platform_driver omap_dsshw_driver = {
.probe = dss_probe, .probe = dss_probe,
.remove = dss_remove, .remove = dss_remove,
.shutdown = dss_shutdown,
.driver = { .driver = {
.name = "omapdss_dss", .name = "omapdss_dss",
.pm = &dss_pm_ops, .pm = &dss_pm_ops,
......
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
#include "omapdss.h" #include "omapdss.h"
#define MAX_DSS_LCD_MANAGERS 3
#define MAX_NUM_DSI 2
#ifdef pr_fmt #ifdef pr_fmt
#undef pr_fmt #undef pr_fmt
#endif #endif
...@@ -72,6 +75,14 @@ ...@@ -72,6 +75,14 @@
#define FLD_MOD(orig, val, start, end) \ #define FLD_MOD(orig, val, start, end) \
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(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 { enum dss_io_pad_mode {
DSS_IO_PAD_MODE_RESET, DSS_IO_PAD_MODE_RESET,
DSS_IO_PAD_MODE_RFBI, DSS_IO_PAD_MODE_RFBI,
...@@ -192,6 +203,11 @@ struct dss_pll { ...@@ -192,6 +203,11 @@ struct dss_pll {
struct dss_pll_clock_info cinfo; struct dss_pll_clock_info cinfo;
}; };
/* Defines a generic omap register field */
struct dss_reg_field {
u8 start, end;
};
struct dispc_clock_info { struct dispc_clock_info {
/* rates that we get with dividers below */ /* rates that we get with dividers below */
unsigned long lck; unsigned long lck;
...@@ -219,10 +235,11 @@ struct seq_file; ...@@ -219,10 +235,11 @@ struct seq_file;
struct platform_device; struct platform_device;
/* core */ /* core */
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask); static inline int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask); {
int dss_set_min_bus_tput(struct device *dev, unsigned long tput); /* To be implemented when the OMAP platform will provide this feature */
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); return 0;
}
static inline bool dss_mgr_is_lcd(enum omap_channel id) 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) ...@@ -234,6 +251,16 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)
} }
/* DSS */ /* 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; int dss_init_platform_driver(void) __init;
void dss_uninit_platform_driver(void); void dss_uninit_platform_driver(void);
...@@ -241,6 +268,8 @@ int dss_runtime_get(void); ...@@ -241,6 +268,8 @@ int dss_runtime_get(void);
void dss_runtime_put(void); void dss_runtime_put(void);
unsigned long dss_get_dispc_clk_rate(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); 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); 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); 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, ...@@ -252,10 +281,6 @@ struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id,
struct regulator *regulator); struct regulator *regulator);
void dss_video_pll_uninit(struct dss_pll *pll); 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_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable);
void dss_sdi_init(int datapairs); void dss_sdi_init(int datapairs);
...@@ -312,11 +337,12 @@ void dsi_irq_handler(void); ...@@ -312,11 +337,12 @@ void dsi_irq_handler(void);
/* DPI */ /* DPI */
#ifdef CONFIG_OMAP2_DSS_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); void dpi_uninit_port(struct device_node *port);
#else #else
static inline int dpi_init_port(struct platform_device *pdev, 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; return 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;
}
}
/*
* 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 { ...@@ -234,6 +234,7 @@ struct hdmi_core_audio_config {
struct hdmi_wp_data { struct hdmi_wp_data {
void __iomem *base; void __iomem *base;
phys_addr_t phys_base; phys_addr_t phys_base;
unsigned int version;
}; };
struct hdmi_pll_data { struct hdmi_pll_data {
...@@ -245,15 +246,24 @@ struct hdmi_pll_data { ...@@ -245,15 +246,24 @@ struct hdmi_pll_data {
struct hdmi_wp_data *wp; struct hdmi_wp_data *wp;
}; };
struct hdmi_phy_features {
bool bist_ctrl;
bool ldo_voltage;
unsigned long max_phy;
};
struct hdmi_phy_data { struct hdmi_phy_data {
void __iomem *base; void __iomem *base;
const struct hdmi_phy_features *features;
u8 lane_function[4]; u8 lane_function[4];
u8 lane_polarity[4]; u8 lane_polarity[4];
}; };
struct hdmi_core_data { struct hdmi_core_data {
void __iomem *base; void __iomem *base;
bool cts_swmode;
bool audio_use_mclk;
}; };
static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx, 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, ...@@ -303,7 +313,8 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
struct videomode *vm); struct videomode *vm);
void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
struct videomode *vm, struct hdmi_config *param); 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); phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
/* HDMI PLL funcs */ /* HDMI PLL funcs */
...@@ -316,7 +327,8 @@ void hdmi_pll_uninit(struct hdmi_pll_data *hpll); ...@@ -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, int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
unsigned long lfbitclk); unsigned long lfbitclk);
void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); 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); int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
/* HDMI common funcs */ /* HDMI common funcs */
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include "omapdss.h" #include "omapdss.h"
#include "hdmi4_core.h" #include "hdmi4_core.h"
#include "dss.h" #include "dss.h"
#include "dss_features.h"
#include "hdmi.h" #include "hdmi.h"
static struct omap_hdmi hdmi; static struct omap_hdmi hdmi;
...@@ -668,7 +667,7 @@ static int hdmi_audio_register(struct device *dev) ...@@ -668,7 +667,7 @@ static int hdmi_audio_register(struct device *dev)
{ {
struct omap_hdmi_audio_pdata pdata = { struct omap_hdmi_audio_pdata pdata = {
.dev = dev, .dev = dev,
.dss_version = omapdss_get_version(), .version = 4,
.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
.ops = &hdmi_audio_ops, .ops = &hdmi_audio_ops,
}; };
...@@ -700,7 +699,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data) ...@@ -700,7 +699,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
if (r) if (r)
return r; return r;
r = hdmi_wp_init(pdev, &hdmi.wp); r = hdmi_wp_init(pdev, &hdmi.wp, 4);
if (r) if (r)
return r; return r;
...@@ -708,7 +707,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data) ...@@ -708,7 +707,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
if (r) if (r)
return r; return r;
r = hdmi_phy_init(pdev, &hdmi.phy); r = hdmi_phy_init(pdev, &hdmi.phy, 4);
if (r) if (r)
goto err; goto err;
......
...@@ -31,11 +31,11 @@ ...@@ -31,11 +31,11 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/sys_soc.h>
#include <sound/asound.h> #include <sound/asound.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
#include "hdmi4_core.h" #include "hdmi4_core.h"
#include "dss_features.h"
#define HDMI_CORE_AV 0x500 #define HDMI_CORE_AV 0x500
...@@ -757,10 +757,10 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, ...@@ -757,10 +757,10 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
/* Audio clock regeneration settings */ /* Audio clock regeneration settings */
acore.n = n; acore.n = n;
acore.cts = cts; acore.cts = cts;
if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { if (core->cts_swmode) {
acore.aud_par_busclk = 0; acore.aud_par_busclk = 0;
acore.cts_mode = HDMI_AUDIO_CTS_MODE_SW; 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 { } else {
acore.aud_par_busclk = (((128 * 31) - 1) << 8); acore.aud_par_busclk = (((128 * 31) - 1) << 8);
acore.cts_mode = HDMI_AUDIO_CTS_MODE_HW; 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) ...@@ -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); 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) int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
{ {
const struct hdmi4_features *features;
struct resource *res; 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"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
core->base = devm_ioremap_resource(&pdev->dev, res); core->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(core->base)) if (IS_ERR(core->base))
......
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#include "omapdss.h" #include "omapdss.h"
#include "hdmi5_core.h" #include "hdmi5_core.h"
#include "dss.h" #include "dss.h"
#include "dss_features.h"
static struct omap_hdmi hdmi; static struct omap_hdmi hdmi;
...@@ -695,7 +694,7 @@ static int hdmi_audio_register(struct device *dev) ...@@ -695,7 +694,7 @@ static int hdmi_audio_register(struct device *dev)
{ {
struct omap_hdmi_audio_pdata pdata = { struct omap_hdmi_audio_pdata pdata = {
.dev = dev, .dev = dev,
.dss_version = omapdss_get_version(), .version = 5,
.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
.ops = &hdmi_audio_ops, .ops = &hdmi_audio_ops,
}; };
...@@ -732,7 +731,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data) ...@@ -732,7 +731,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data)
if (r) if (r)
return r; return r;
r = hdmi_wp_init(pdev, &hdmi.wp); r = hdmi_wp_init(pdev, &hdmi.wp, 5);
if (r) if (r)
return r; return r;
...@@ -740,7 +739,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data) ...@@ -740,7 +739,7 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data)
if (r) if (r)
return r; return r;
r = hdmi_phy_init(pdev, &hdmi.phy); r = hdmi_phy_init(pdev, &hdmi.phy, 5);
if (r) if (r)
goto err; goto err;
......
...@@ -19,14 +19,6 @@ ...@@ -19,14 +19,6 @@
#include "dss.h" #include "dss.h"
#include "hdmi.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) void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
{ {
#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ #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) ...@@ -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_DIGITAL_CTRL);
DUMPPHY(HDMI_TXPHY_POWER_CTRL); DUMPPHY(HDMI_TXPHY_POWER_CTRL);
DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
if (phy_feat->bist_ctrl) if (phy->features->bist_ctrl)
DUMPPHY(HDMI_TXPHY_BIST_CONTROL); DUMPPHY(HDMI_TXPHY_BIST_CONTROL);
} }
...@@ -146,7 +138,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk, ...@@ -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 * In OMAP5+, the HFBITCLK must be divided by 2 before issuing the
* HDMI_PHYPWRCMD_LDOON command. * 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); 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, ...@@ -155,7 +147,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
*/ */
if (hfbitclk != lfbitclk) if (hfbitclk != lfbitclk)
freqout = 0; freqout = 0;
else if (hfbitclk / 10 < phy_feat->max_phy) else if (hfbitclk / 10 < phy->features->max_phy)
freqout = 1; freqout = 1;
else else
freqout = 2; freqout = 2;
...@@ -170,7 +162,7 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk, ...@@ -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); hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
/* Setup max LDO voltage */ /* 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); REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
hdmi_phy_configure_lanes(phy); hdmi_phy_configure_lanes(phy);
...@@ -190,47 +182,15 @@ static const struct hdmi_phy_features omap54xx_phy_feats = { ...@@ -190,47 +182,15 @@ static const struct hdmi_phy_features omap54xx_phy_feats = {
.max_phy = 186000000, .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; struct resource *res;
r = hdmi_phy_init_features(pdev); if (version == 4)
if (r) phy->features = &omap44xx_phy_feats;
return r; else
phy->features = &omap54xx_phy_feats;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
phy->base = devm_ioremap_resource(&pdev->dev, res); phy->base = devm_ioremap_resource(&pdev->dev, res);
......
...@@ -71,7 +71,7 @@ static void hdmi_pll_disable(struct dss_pll *dsspll) ...@@ -71,7 +71,7 @@ static void hdmi_pll_disable(struct dss_pll *dsspll)
WARN_ON(r < 0 && r != -ENOSYS); 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, .enable = hdmi_pll_enable,
.disable = hdmi_pll_disable, .disable = hdmi_pll_disable,
.set_config = dss_pll_write_config_type_b, .set_config = dss_pll_write_config_type_b,
...@@ -128,7 +128,8 @@ static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = { ...@@ -128,7 +128,8 @@ static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
.has_refsel = true, .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 dss_pll *pll = &hpll->pll;
struct clk *clk; struct clk *clk;
...@@ -145,23 +146,12 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data ...@@ -145,23 +146,12 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data
pll->base = hpll->base; pll->base = hpll->base;
pll->clkin = clk; pll->clkin = clk;
switch (omapdss_get_version()) { if (hpll->wp->version == 4)
case OMAPDSS_VER_OMAP4430_ES1:
case OMAPDSS_VER_OMAP4430_ES2:
case OMAPDSS_VER_OMAP4:
pll->hw = &dss_omap4_hdmi_pll_hw; pll->hw = &dss_omap4_hdmi_pll_hw;
break; else
case OMAPDSS_VER_OMAP5:
case OMAPDSS_VER_DRA7xx:
pll->hw = &dss_omap5_hdmi_pll_hw; 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); r = dss_pll_register(pll);
if (r) if (r)
...@@ -184,7 +174,7 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll, ...@@ -184,7 +174,7 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
if (IS_ERR(pll->base)) if (IS_ERR(pll->base))
return PTR_ERR(pll->base); return PTR_ERR(pll->base);
r = dsi_init_pll_data(pdev, pll); r = hdmi_init_pll_data(pdev, pll);
if (r) { if (r) {
DSSERR("failed to init HDMI PLL\n"); DSSERR("failed to init HDMI PLL\n");
return r; return r;
......
...@@ -178,9 +178,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, ...@@ -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 * However, we don't support OMAP5 ES1 at all, so we can just check for
* OMAP4 here. * OMAP4 here.
*/ */
if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 || if (wp->version == 4)
omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||
omapdss_get_version() == OMAPDSS_VER_OMAP4)
hsync_len_offset = 0; hsync_len_offset = 0;
timing_h |= FLD_VAL(vm->hback_porch, 31, 20); timing_h |= FLD_VAL(vm->hback_porch, 31, 20);
...@@ -235,9 +233,7 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, ...@@ -235,9 +233,7 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
DSSDBG("Enter hdmi_wp_audio_config_format\n"); DSSDBG("Enter hdmi_wp_audio_config_format\n");
r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG); r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 || if (wp->version == 4) {
omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||
omapdss_get_version() == OMAPDSS_VER_OMAP4) {
r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); 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) ...@@ -282,7 +278,8 @@ int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
return 0; 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; struct resource *res;
...@@ -292,6 +289,7 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp) ...@@ -292,6 +289,7 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
return PTR_ERR(wp->base); return PTR_ERR(wp->base);
wp->phys_base = res->start; wp->phys_base = res->start;
wp->version = version;
return 0; return 0;
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <video/videomode.h> #include <video/videomode.h>
#include <linux/platform_data/omapdss.h> #include <linux/platform_data/omapdss.h>
#include <uapi/drm/drm_mode.h> #include <uapi/drm/drm_mode.h>
#include <drm/drm_crtc.h>
#define DISPC_IRQ_FRAMEDONE (1 << 0) #define DISPC_IRQ_FRAMEDONE (1 << 0)
#define DISPC_IRQ_VSYNC (1 << 1) #define DISPC_IRQ_VSYNC (1 << 1)
...@@ -241,13 +242,6 @@ struct omap_dss_dsi_config { ...@@ -241,13 +242,6 @@ struct omap_dss_dsi_config {
enum omap_dss_dsi_trans_mode trans_mode; 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 { struct omap_dss_cpr_coefs {
s16 rr, rg, rb; s16 rr, rg, rb;
s16 gr, gg, gb; s16 gr, gg, gb;
...@@ -403,6 +397,14 @@ struct omapdss_hdmi_ops { ...@@ -403,6 +397,14 @@ struct omapdss_hdmi_ops {
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
bool (*detect)(struct omap_dss_device *dssdev); 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_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
int (*set_infoframe)(struct omap_dss_device *dssdev, int (*set_infoframe)(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi); const struct hdmi_avi_infoframe *avi);
...@@ -567,12 +569,19 @@ struct omap_dss_driver { ...@@ -567,12 +569,19 @@ struct omap_dss_driver {
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
bool (*detect)(struct omap_dss_device *dssdev); 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_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev, int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi); const struct hdmi_avi_infoframe *avi);
}; };
enum omapdss_version omapdss_get_version(void);
bool omapdss_is_initialized(void); bool omapdss_is_initialized(void);
int omap_dss_register_driver(struct omap_dss_driver *); int omap_dss_register_driver(struct omap_dss_driver *);
......
...@@ -37,10 +37,10 @@ ...@@ -37,10 +37,10 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/sys_soc.h>
#include "omapdss.h" #include "omapdss.h"
#include "dss.h" #include "dss.h"
#include "dss_features.h"
/* Venc registers */ /* Venc registers */
#define VENC_REV_ID 0x00 #define VENC_REV_ID 0x00
...@@ -263,7 +263,7 @@ static const struct venc_config venc_config_pal_bdghi = { ...@@ -263,7 +263,7 @@ static const struct venc_config venc_config_pal_bdghi = {
.fid_ext_start_y__fid_ext_offset_y = 0x01380005, .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, .hactive = 720,
.vactive = 574, .vactive = 574,
.pixelclock = 13500000, .pixelclock = 13500000,
...@@ -279,9 +279,8 @@ const struct videomode omap_dss_pal_vm = { ...@@ -279,9 +279,8 @@ const struct videomode omap_dss_pal_vm = {
DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_PIXDATA_POSEDGE |
DISPLAY_FLAGS_SYNC_NEGEDGE, 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, .hactive = 720,
.vactive = 482, .vactive = 482,
.pixelclock = 13500000, .pixelclock = 13500000,
...@@ -297,7 +296,6 @@ const struct videomode omap_dss_ntsc_vm = { ...@@ -297,7 +296,6 @@ const struct videomode omap_dss_ntsc_vm = {
DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_PIXDATA_POSEDGE |
DISPLAY_FLAGS_SYNC_NEGEDGE, DISPLAY_FLAGS_SYNC_NEGEDGE,
}; };
EXPORT_SYMBOL(omap_dss_ntsc_vm);
static struct { static struct {
struct platform_device *pdev; struct platform_device *pdev;
...@@ -311,6 +309,7 @@ static struct { ...@@ -311,6 +309,7 @@ static struct {
struct videomode vm; struct videomode vm;
enum omap_dss_venc_type type; enum omap_dss_venc_type type;
bool invert_polarity; bool invert_polarity;
bool requires_tv_dac_clk;
struct omap_dss_device output; struct omap_dss_device output;
} venc; } venc;
...@@ -693,7 +692,7 @@ static int venc_get_clocks(struct platform_device *pdev) ...@@ -693,7 +692,7 @@ static int venc_get_clocks(struct platform_device *pdev)
{ {
struct clk *clk; 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"); clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
DSSERR("can't get tv_dac_clk\n"); DSSERR("can't get tv_dac_clk\n");
...@@ -828,6 +827,12 @@ static int venc_probe_of(struct platform_device *pdev) ...@@ -828,6 +827,12 @@ static int venc_probe_of(struct platform_device *pdev)
} }
/* VENC HW IP initialisation */ /* 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) static int venc_bind(struct device *dev, struct device *master, void *data)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
...@@ -837,6 +842,10 @@ static int venc_bind(struct device *dev, struct device *master, void *data) ...@@ -837,6 +842,10 @@ static int venc_bind(struct device *dev, struct device *master, void *data)
venc.pdev = pdev; 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); mutex_init(&venc.venc_lock);
venc.wss_data = 0; venc.wss_data = 0;
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "omapdss.h" #include "omapdss.h"
#include "dss.h" #include "dss.h"
#include "dss_features.h"
struct dss_video_pll { struct dss_video_pll {
struct dss_pll pll; struct dss_pll pll;
......
...@@ -35,6 +35,23 @@ struct omap_connector { ...@@ -35,6 +35,23 @@ struct omap_connector {
bool hdmi_mode; 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) bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
{ {
struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_connector *omap_connector = to_omap_connector(connector);
...@@ -75,6 +92,10 @@ static void omap_connector_destroy(struct drm_connector *connector) ...@@ -75,6 +92,10 @@ static void omap_connector_destroy(struct drm_connector *connector)
struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_device *dssdev = omap_connector->dssdev;
DBG("%s", omap_connector->dssdev->name); 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_unregister(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(omap_connector); kfree(omap_connector);
...@@ -215,6 +236,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, ...@@ -215,6 +236,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
{ {
struct drm_connector *connector = NULL; struct drm_connector *connector = NULL;
struct omap_connector *omap_connector; struct omap_connector *omap_connector;
bool hpd_supported = false;
DBG("%s", dssdev->name); DBG("%s", dssdev->name);
...@@ -232,7 +254,20 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, ...@@ -232,7 +254,20 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
connector_type); connector_type);
drm_connector_helper_add(connector, &omap_connector_helper_funcs); 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 | connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT; DRM_CONNECTOR_POLL_DISCONNECT;
else else
......
...@@ -589,7 +589,9 @@ omap_crtc_duplicate_state(struct drm_crtc *crtc) ...@@ -589,7 +589,9 @@ omap_crtc_duplicate_state(struct drm_crtc *crtc)
current_state = to_omap_crtc_state(crtc->state); current_state = to_omap_crtc_state(crtc->state);
state = kmalloc(sizeof(*state), GFP_KERNEL); state = kmalloc(sizeof(*state), GFP_KERNEL);
if (state) if (!state)
return NULL;
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
state->zpos = current_state->zpos; state->zpos = current_state->zpos;
......
...@@ -323,6 +323,32 @@ static int omap_modeset_init(struct drm_device *dev) ...@@ -323,6 +323,32 @@ static int omap_modeset_init(struct drm_device *dev)
return 0; 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 * drm ioctl funcs
*/ */
...@@ -438,44 +464,11 @@ static int dev_open(struct drm_device *dev, struct drm_file *file) ...@@ -438,44 +464,11 @@ static int dev_open(struct drm_device *dev, struct drm_file *file)
*/ */
static void dev_lastclose(struct drm_device *dev) 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; struct omap_drm_private *priv = dev->dev_private;
int ret; int ret;
DBG("lastclose: dev=%p", dev); 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) { if (priv->fbdev) {
ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev); ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
if (ret) if (ret)
...@@ -549,6 +542,12 @@ static int pdev_probe(struct platform_device *pdev) ...@@ -549,6 +542,12 @@ static int pdev_probe(struct platform_device *pdev)
if (omapdss_is_initialized() == false) if (omapdss_is_initialized() == false)
return -EPROBE_DEFER; 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(); omap_crtc_pre_init();
ret = omap_connect_dssdevs(); ret = omap_connect_dssdevs();
...@@ -602,6 +601,7 @@ static int pdev_probe(struct platform_device *pdev) ...@@ -602,6 +601,7 @@ static int pdev_probe(struct platform_device *pdev)
priv->fbdev = omap_fbdev_init(ddev); priv->fbdev = omap_fbdev_init(ddev);
drm_kms_helper_poll_init(ddev); drm_kms_helper_poll_init(ddev);
omap_modeset_enable_external_hpd();
/* /*
* Register the DRM device with the core and the connectors with * Register the DRM device with the core and the connectors with
...@@ -614,6 +614,7 @@ static int pdev_probe(struct platform_device *pdev) ...@@ -614,6 +614,7 @@ static int pdev_probe(struct platform_device *pdev)
return 0; return 0;
err_cleanup_helpers: err_cleanup_helpers:
omap_modeset_disable_external_hpd();
drm_kms_helper_poll_fini(ddev); drm_kms_helper_poll_fini(ddev);
if (priv->fbdev) if (priv->fbdev)
omap_fbdev_free(ddev); omap_fbdev_free(ddev);
...@@ -642,6 +643,7 @@ static int pdev_remove(struct platform_device *pdev) ...@@ -642,6 +643,7 @@ static int pdev_remove(struct platform_device *pdev)
drm_dev_unregister(ddev); drm_dev_unregister(ddev);
omap_modeset_disable_external_hpd();
drm_kms_helper_poll_fini(ddev); drm_kms_helper_poll_fini(ddev);
if (priv->fbdev) if (priv->fbdev)
...@@ -733,7 +735,7 @@ static SIMPLE_DEV_PM_OPS(omapdrm_pm_ops, omap_drm_suspend, omap_drm_resume); ...@@ -733,7 +735,7 @@ static SIMPLE_DEV_PM_OPS(omapdrm_pm_ops, omap_drm_suspend, omap_drm_resume);
static struct platform_driver pdev = { static struct platform_driver pdev = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = "omapdrm",
.pm = &omapdrm_pm_ops, .pm = &omapdrm_pm_ops,
}, },
.probe = pdev_probe, .probe = pdev_probe,
......
...@@ -379,7 +379,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, ...@@ -379,7 +379,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
return fb; return fb;
error: error:
while (--i > 0) while (--i >= 0)
drm_gem_object_unreference_unlocked(bos[i]); drm_gem_object_unreference_unlocked(bos[i]);
return fb; return fb;
......
...@@ -144,7 +144,7 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer, ...@@ -144,7 +144,7 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
return omap_gem_mmap_obj(obj, vma); 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, .map_dma_buf = omap_gem_map_dma_buf,
.unmap_dma_buf = omap_gem_unmap_dma_buf, .unmap_dma_buf = omap_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release, .release = drm_gem_dmabuf_release,
......
...@@ -664,7 +664,7 @@ static int hdmi_audio_register(struct device *dev) ...@@ -664,7 +664,7 @@ static int hdmi_audio_register(struct device *dev)
{ {
struct omap_hdmi_audio_pdata pdata = { struct omap_hdmi_audio_pdata pdata = {
.dev = dev, .dev = dev,
.dss_version = omapdss_get_version(), .version = 4,
.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
.ops = &hdmi_audio_ops, .ops = &hdmi_audio_ops,
}; };
......
...@@ -695,7 +695,7 @@ static int hdmi_audio_register(struct device *dev) ...@@ -695,7 +695,7 @@ static int hdmi_audio_register(struct device *dev)
{ {
struct omap_hdmi_audio_pdata pdata = { struct omap_hdmi_audio_pdata pdata = {
.dev = dev, .dev = dev,
.dss_version = omapdss_get_version(), .version = 5,
.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
.ops = &hdmi_audio_ops, .ops = &hdmi_audio_ops,
}; };
......
/*
* 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 { ...@@ -39,7 +39,7 @@ struct omap_hdmi_audio_ops {
/* HDMI audio initalization data */ /* HDMI audio initalization data */
struct omap_hdmi_audio_pdata { struct omap_hdmi_audio_pdata {
struct device *dev; struct device *dev;
enum omapdss_version dss_version; unsigned int version;
phys_addr_t audio_dma_addr; phys_addr_t audio_dma_addr;
const struct omap_hdmi_audio_ops *ops; const struct omap_hdmi_audio_ops *ops;
......
...@@ -337,14 +337,11 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) ...@@ -337,14 +337,11 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev)
ad->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ad->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
mutex_init(&ad->current_stream_lock); mutex_init(&ad->current_stream_lock);
switch (ha->dss_version) { switch (ha->version) {
case OMAPDSS_VER_OMAP4430_ES1: case 4:
case OMAPDSS_VER_OMAP4430_ES2:
case OMAPDSS_VER_OMAP4:
dai_drv = &omap4_hdmi_dai; dai_drv = &omap4_hdmi_dai;
break; break;
case OMAPDSS_VER_OMAP5: case 5:
case OMAPDSS_VER_DRA7xx:
dai_drv = &omap5_hdmi_dai; dai_drv = &omap5_hdmi_dai;
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment