Omapdss patches for 3.10 merge window
The biggest changes are: * DSI video mode: automatic clock and timing calculation * Lots of platform data related panel driver cleanups, to prepare for DT -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJRa8O6AAoJEPo9qoy8lh718hgP/2G/TUDm7T7Ss3qMA/U+tVbu GgMuzdoy7IXOH5RrY6LSzD5pGfRGO8+XEctCJ4tZjFcX6Kk1aA0Ueq6byyXirhh1 uQ9RwID92qtJaM14sOouhwPoPsaXAeH2mHYgzoC+M2ur10oBC9DImwA6UoAmKSae O8IVeRC0F9AtfSBBA0xV4hXAGeSEdzhs/SGFkHBIUsFqvjQNqTF+Eoe4FR0b9cuT V7ai2489vn47yK8jH2ICVJA5toaIdEpY9WD/l8r8fJFmkXGo2/mHb3M2AnNgyEuL MswrI7J3AKi+l3crskaATUuMNs2K+NfBemj6zgjGGjLbj9AKRAFuDqB9gCs+aR5a kyYNe88QOrdfhqRZxBzVWHfUyXFb7no2dnxwryl9/JEHt6GWOBzl/BlXRvBmn4bL 6U6bIiEwNUpNKVc6kgDx9lPyXfBA7h12QqUh7IrjhlI1oXCJM7S6OaIor11IwyJt BaoojM2raZACbJg2Pt0SYiaTNTSIE2L6qqg6PXkR9O9nFSy+/CmX9tlqIat++2ZC Yl3I3pg7BlqXmEWsE8dT6MMf068R91BDUXkhC9pO+gefzUXOUduAFIqQTC1A6azo qzPI92Bd+GSIsKqpykSWGd91HlLpRFfujtqoMhIrceK6QecX661on5A7PpxRsI86 hghEURd+VpUjD2ECgdT2 =C4zn -----END PGP SIGNATURE----- Merge tag 'omapdss-for-3.10' of git://gitorious.org/linux-omap-dss2/linux into drm-next Omapdss patches for 3.10 merge window The biggest changes are: * DSI video mode: automatic clock and timing calculation * Lots of platform data related panel driver cleanups, to prepare for DT * tag 'omapdss-for-3.10' of git://gitorious.org/linux-omap-dss2/linux: (69 commits) drm/omap: add statics to a few structs drm/omap: Fix and improve crtc and overlay manager correlation drm/omap: Take a fb reference in omap_plane_update() drm/omap: Make fixed resolution panels work drm/omap: fix modeset_init if a panel doesn't satisfy omapdrm requirements OMAPDSS: DPI: widen the pck search when using dss fck OMAPDSS: fix dss_fck clock rate rounding omapdss: use devm_clk_get() OMAPDSS: nec-nl8048 panel: Use dev_pm_ops OMAPDSS: DISPC: Revert to older DISPC Smart Standby mechanism for OMAP5 OMAPDSS: DISPC: Configure doublestride for NV12 when using 2D Tiler buffers omapdss: Features: Fix some parameter ranges omapdss: DISPC: add max pixel clock limits for LCD and TV managers OMAPDSS: DSI: Use devm_clk_get() drivers: video: omap2: dss: Use PTR_RET function OMAPDSS: VENC: remove platform_enable/disable calls OMAPDSS: n8x0 panel: remove use of platform_enable/disable OMAPDSS: n8x0 panel: handle gpio data in panel driver OMAPDSS: picodlp panel: remove platform_enable/disable callbacks OMAPDSS: picodlp panel: handle gpio data in panel driver ...
This commit is contained in:
commit
dea14dfab9
|
@ -38,7 +38,7 @@
|
|||
#include "gpmc-smc91x.h"
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "mux.h"
|
||||
#include "hsmmc.h"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "common.h"
|
||||
#include <linux/omap-dma.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "gpmc.h"
|
||||
#include "gpmc-smc91x.h"
|
||||
|
|
|
@ -35,8 +35,7 @@
|
|||
|
||||
#include "common.h"
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "am35xx-emac.h"
|
||||
#include "mux.h"
|
||||
|
|
|
@ -41,8 +41,7 @@
|
|||
|
||||
#include <linux/platform_data/mtd-nand-omap2.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
||||
#include "common.h"
|
||||
|
|
|
@ -43,8 +43,7 @@
|
|||
#include "gpmc.h"
|
||||
#include <linux/platform_data/mtd-nand-omap2.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <asm/mach/map.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "mux.h"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <asm/mach/arch.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
#include <linux/platform_data/mtd-onenand-omap2.h>
|
||||
|
||||
#include "common.h"
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "gpmc-smsc911x.h"
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "board-flash.h"
|
||||
#include "mux.h"
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include <asm/mach/flash.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
#include <linux/platform_data/mtd-nand-omap2.h>
|
||||
|
||||
#include "common.h"
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#include "common.h"
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "mux.h"
|
||||
|
|
|
@ -44,8 +44,7 @@
|
|||
#include "gpmc.h"
|
||||
#include <linux/platform_data/mtd-nand-omap2.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
||||
|
|
|
@ -47,8 +47,7 @@
|
|||
#include <asm/mach/map.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "mux.h"
|
||||
|
|
|
@ -27,9 +27,7 @@
|
|||
#include <linux/gpio.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-nokia-dsi.h>
|
||||
#include <video/omap-panel-picodlp.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "dss-common.h"
|
||||
|
|
|
@ -110,6 +110,11 @@ static enum drm_connector_status omap_connector_detect(
|
|||
ret = connector_status_connected;
|
||||
else
|
||||
ret = connector_status_disconnected;
|
||||
} else if (dssdev->type == OMAP_DISPLAY_TYPE_DPI ||
|
||||
dssdev->type == OMAP_DISPLAY_TYPE_DBI ||
|
||||
dssdev->type == OMAP_DISPLAY_TYPE_SDI ||
|
||||
dssdev->type == OMAP_DISPLAY_TYPE_DSI) {
|
||||
ret = connector_status_connected;
|
||||
} else {
|
||||
ret = connector_status_unknown;
|
||||
}
|
||||
|
@ -189,12 +194,30 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
|
|||
struct omap_video_timings timings = {0};
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_display_mode *new_mode;
|
||||
int ret = MODE_BAD;
|
||||
int r, ret = MODE_BAD;
|
||||
|
||||
copy_timings_drm_to_omap(&timings, mode);
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
if (!dssdrv->check_timings(dssdev, &timings)) {
|
||||
/*
|
||||
* if the panel driver doesn't have a check_timings, it's most likely
|
||||
* a fixed resolution panel, check if the timings match with the
|
||||
* panel's timings
|
||||
*/
|
||||
if (dssdrv->check_timings) {
|
||||
r = dssdrv->check_timings(dssdev, &timings);
|
||||
} else {
|
||||
struct omap_video_timings t = {0};
|
||||
|
||||
dssdrv->get_timings(dssdev, &t);
|
||||
|
||||
if (memcmp(&timings, &t, sizeof(struct omap_video_timings)))
|
||||
r = -EINVAL;
|
||||
else
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
/* check if vrefresh is still valid */
|
||||
new_mode = drm_mode_duplicate(dev, mode);
|
||||
new_mode->clock = timings.pixel_clock;
|
||||
|
|
|
@ -74,6 +74,13 @@ struct omap_crtc {
|
|||
struct work_struct page_flip_work;
|
||||
};
|
||||
|
||||
uint32_t pipe2vbl(struct drm_crtc *crtc)
|
||||
{
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
|
||||
return dispc_mgr_get_vsync_irq(omap_crtc->channel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Manager-ops, callbacks from output when they need to configure
|
||||
* the upstream part of the video pipe.
|
||||
|
@ -613,7 +620,13 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
|
|||
omap_crtc->apply.pre_apply = omap_crtc_pre_apply;
|
||||
omap_crtc->apply.post_apply = omap_crtc_post_apply;
|
||||
|
||||
omap_crtc->apply_irq.irqmask = pipe2vbl(id);
|
||||
omap_crtc->channel = channel;
|
||||
omap_crtc->plane = plane;
|
||||
omap_crtc->plane->crtc = crtc;
|
||||
omap_crtc->name = channel_names[channel];
|
||||
omap_crtc->pipe = id;
|
||||
|
||||
omap_crtc->apply_irq.irqmask = pipe2vbl(crtc);
|
||||
omap_crtc->apply_irq.irq = omap_crtc_apply_irq;
|
||||
|
||||
omap_crtc->error_irq.irqmask =
|
||||
|
@ -621,12 +634,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
|
|||
omap_crtc->error_irq.irq = omap_crtc_error_irq;
|
||||
omap_irq_register(dev, &omap_crtc->error_irq);
|
||||
|
||||
omap_crtc->channel = channel;
|
||||
omap_crtc->plane = plane;
|
||||
omap_crtc->plane->crtc = crtc;
|
||||
omap_crtc->name = channel_names[channel];
|
||||
omap_crtc->pipe = id;
|
||||
|
||||
/* temporary: */
|
||||
omap_crtc->mgr.id = channel;
|
||||
|
||||
|
|
|
@ -74,54 +74,53 @@ static int get_connector_type(struct omap_dss_device *dssdev)
|
|||
}
|
||||
}
|
||||
|
||||
static bool channel_used(struct drm_device *dev, enum omap_channel channel)
|
||||
{
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->num_crtcs; i++) {
|
||||
struct drm_crtc *crtc = priv->crtcs[i];
|
||||
|
||||
if (omap_crtc_channel(crtc) == channel)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int omap_modeset_init(struct drm_device *dev)
|
||||
{
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
int num_ovls = dss_feat_get_num_ovls();
|
||||
int id;
|
||||
int num_mgrs = dss_feat_get_num_mgrs();
|
||||
int num_crtcs;
|
||||
int i, id = 0;
|
||||
|
||||
drm_mode_config_init(dev);
|
||||
|
||||
omap_drm_irq_install(dev);
|
||||
|
||||
/*
|
||||
* Create private planes and CRTCs for the last NUM_CRTCs overlay
|
||||
* plus manager:
|
||||
* We usually don't want to create a CRTC for each manager, at least
|
||||
* not until we have a way to expose private planes to userspace.
|
||||
* Otherwise there would not be enough video pipes left for drm planes.
|
||||
* We use the num_crtc argument to limit the number of crtcs we create.
|
||||
*/
|
||||
for (id = 0; id < min(num_crtc, num_ovls); id++) {
|
||||
struct drm_plane *plane;
|
||||
struct drm_crtc *crtc;
|
||||
num_crtcs = min3(num_crtc, num_mgrs, num_ovls);
|
||||
|
||||
plane = omap_plane_init(dev, id, true);
|
||||
crtc = omap_crtc_init(dev, plane, pipe2chan(id), id);
|
||||
|
||||
BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
|
||||
priv->crtcs[id] = crtc;
|
||||
priv->num_crtcs++;
|
||||
|
||||
priv->planes[id] = plane;
|
||||
priv->num_planes++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create normal planes for the remaining overlays:
|
||||
*/
|
||||
for (; id < num_ovls; id++) {
|
||||
struct drm_plane *plane = omap_plane_init(dev, id, false);
|
||||
|
||||
BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
|
||||
priv->planes[priv->num_planes++] = plane;
|
||||
}
|
||||
dssdev = NULL;
|
||||
|
||||
for_each_dss_dev(dssdev) {
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
enum omap_channel channel;
|
||||
|
||||
if (!dssdev->driver) {
|
||||
dev_warn(dev->dev, "%s has no driver.. skipping it\n",
|
||||
dssdev->name);
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(dssdev->driver->get_timings ||
|
||||
|
@ -129,7 +128,7 @@ static int omap_modeset_init(struct drm_device *dev)
|
|||
dev_warn(dev->dev, "%s driver does not support "
|
||||
"get_timings or read_edid.. skipping it!\n",
|
||||
dssdev->name);
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
encoder = omap_encoder_init(dev, dssdev);
|
||||
|
@ -157,16 +156,118 @@ static int omap_modeset_init(struct drm_device *dev)
|
|||
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
|
||||
/*
|
||||
* if we have reached the limit of the crtcs we are allowed to
|
||||
* create, let's not try to look for a crtc for this
|
||||
* panel/encoder and onwards, we will, of course, populate the
|
||||
* the possible_crtcs field for all the encoders with the final
|
||||
* set of crtcs we create
|
||||
*/
|
||||
if (id == num_crtcs)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* get the recommended DISPC channel for this encoder. For now,
|
||||
* we only try to get create a crtc out of the recommended, the
|
||||
* other possible channels to which the encoder can connect are
|
||||
* not considered.
|
||||
*/
|
||||
channel = dssdev->output->dispc_channel;
|
||||
|
||||
/*
|
||||
* if this channel hasn't already been taken by a previously
|
||||
* allocated crtc, we create a new crtc for it
|
||||
*/
|
||||
if (!channel_used(dev, channel)) {
|
||||
struct drm_plane *plane;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
plane = omap_plane_init(dev, id, true);
|
||||
crtc = omap_crtc_init(dev, plane, channel, id);
|
||||
|
||||
BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
|
||||
priv->crtcs[id] = crtc;
|
||||
priv->num_crtcs++;
|
||||
|
||||
priv->planes[id] = plane;
|
||||
priv->num_planes++;
|
||||
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we have allocated crtcs according to the need of the panels/encoders,
|
||||
* adding more crtcs here if needed
|
||||
*/
|
||||
for (; id < num_crtcs; id++) {
|
||||
|
||||
/* find a free manager for this crtc */
|
||||
for (i = 0; i < num_mgrs; i++) {
|
||||
if (!channel_used(dev, i)) {
|
||||
struct drm_plane *plane;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
plane = omap_plane_init(dev, id, true);
|
||||
crtc = omap_crtc_init(dev, plane, i, id);
|
||||
|
||||
BUG_ON(priv->num_crtcs >=
|
||||
ARRAY_SIZE(priv->crtcs));
|
||||
|
||||
priv->crtcs[id] = crtc;
|
||||
priv->num_crtcs++;
|
||||
|
||||
priv->planes[id] = plane;
|
||||
priv->num_planes++;
|
||||
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == num_mgrs) {
|
||||
/* this shouldn't really happen */
|
||||
dev_err(dev->dev, "no managers left for crtc\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create normal planes for the remaining overlays:
|
||||
*/
|
||||
for (; id < num_ovls; id++) {
|
||||
struct drm_plane *plane = omap_plane_init(dev, id, false);
|
||||
|
||||
BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
|
||||
priv->planes[priv->num_planes++] = plane;
|
||||
}
|
||||
|
||||
for (i = 0; i < priv->num_encoders; i++) {
|
||||
struct drm_encoder *encoder = priv->encoders[i];
|
||||
struct omap_dss_device *dssdev =
|
||||
omap_encoder_get_dssdev(encoder);
|
||||
|
||||
/* figure out which crtc's we can connect the encoder to: */
|
||||
encoder->possible_crtcs = 0;
|
||||
for (id = 0; id < priv->num_crtcs; id++) {
|
||||
enum omap_dss_output_id supported_outputs =
|
||||
dss_feat_get_supported_outputs(pipe2chan(id));
|
||||
struct drm_crtc *crtc = priv->crtcs[id];
|
||||
enum omap_channel crtc_channel;
|
||||
enum omap_dss_output_id supported_outputs;
|
||||
|
||||
crtc_channel = omap_crtc_channel(crtc);
|
||||
supported_outputs =
|
||||
dss_feat_get_supported_outputs(crtc_channel);
|
||||
|
||||
if (supported_outputs & dssdev->output->id)
|
||||
encoder->possible_crtcs |= (1 << id);
|
||||
}
|
||||
}
|
||||
|
||||
DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n",
|
||||
priv->num_planes, priv->num_crtcs, priv->num_encoders,
|
||||
priv->num_connectors);
|
||||
|
||||
dev->mode_config.min_width = 32;
|
||||
dev->mode_config.min_height = 32;
|
||||
|
||||
|
@ -303,7 +404,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
|
||||
static struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
|
||||
DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),
|
||||
|
@ -567,7 +668,7 @@ static const struct dev_pm_ops omapdrm_pm_ops = {
|
|||
};
|
||||
#endif
|
||||
|
||||
struct platform_driver pdev = {
|
||||
static struct platform_driver pdev = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -139,8 +139,8 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
|
|||
int omap_gem_resume(struct device *dev);
|
||||
#endif
|
||||
|
||||
int omap_irq_enable_vblank(struct drm_device *dev, int crtc);
|
||||
void omap_irq_disable_vblank(struct drm_device *dev, int crtc);
|
||||
int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id);
|
||||
void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id);
|
||||
irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
|
||||
void omap_irq_preinstall(struct drm_device *dev);
|
||||
int omap_irq_postinstall(struct drm_device *dev);
|
||||
|
@ -271,39 +271,9 @@ static inline int align_pitch(int pitch, int width, int bpp)
|
|||
return ALIGN(pitch, 8 * bytespp);
|
||||
}
|
||||
|
||||
static inline enum omap_channel pipe2chan(int pipe)
|
||||
{
|
||||
int num_mgrs = dss_feat_get_num_mgrs();
|
||||
|
||||
/*
|
||||
* We usually don't want to create a CRTC for each manager,
|
||||
* at least not until we have a way to expose private planes
|
||||
* to userspace. Otherwise there would not be enough video
|
||||
* pipes left for drm planes. The higher #'d managers tend
|
||||
* to have more features so start in reverse order.
|
||||
*/
|
||||
return num_mgrs - pipe - 1;
|
||||
}
|
||||
|
||||
/* map crtc to vblank mask */
|
||||
static inline uint32_t pipe2vbl(int crtc)
|
||||
{
|
||||
enum omap_channel channel = pipe2chan(crtc);
|
||||
return dispc_mgr_get_vsync_irq(channel);
|
||||
}
|
||||
|
||||
static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
{
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++)
|
||||
if (priv->crtcs[i] == crtc)
|
||||
return i;
|
||||
|
||||
BUG(); /* bogus CRTC ptr */
|
||||
return -1;
|
||||
}
|
||||
uint32_t pipe2vbl(struct drm_crtc *crtc);
|
||||
struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);
|
||||
|
||||
/* should these be made into common util helpers?
|
||||
*/
|
||||
|
|
|
@ -41,6 +41,13 @@ struct omap_encoder {
|
|||
struct omap_dss_device *dssdev;
|
||||
};
|
||||
|
||||
struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder)
|
||||
{
|
||||
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
|
||||
|
||||
return omap_encoder->dssdev;
|
||||
}
|
||||
|
||||
static void omap_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
|
||||
|
@ -128,13 +135,26 @@ int omap_encoder_update(struct drm_encoder *encoder,
|
|||
|
||||
dssdev->output->manager = mgr;
|
||||
|
||||
ret = dssdrv->check_timings(dssdev, timings);
|
||||
if (dssdrv->check_timings) {
|
||||
ret = dssdrv->check_timings(dssdev, timings);
|
||||
} else {
|
||||
struct omap_video_timings t = {0};
|
||||
|
||||
dssdrv->get_timings(dssdev, &t);
|
||||
|
||||
if (memcmp(timings, &t, sizeof(struct omap_video_timings)))
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "could not set timings: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dssdrv->set_timings(dssdev, timings);
|
||||
if (dssdrv->set_timings)
|
||||
dssdrv->set_timings(dssdev, timings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ out_unlock:
|
|||
return omap_gem_mmap_obj(obj, vma);
|
||||
}
|
||||
|
||||
struct dma_buf_ops omap_dmabuf_ops = {
|
||||
static struct dma_buf_ops omap_dmabuf_ops = {
|
||||
.map_dma_buf = omap_gem_map_dma_buf,
|
||||
.unmap_dma_buf = omap_gem_unmap_dma_buf,
|
||||
.release = omap_gem_dmabuf_release,
|
||||
|
|
|
@ -130,12 +130,13 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
|
|||
* Zero on success, appropriate errno if the given @crtc's vblank
|
||||
* interrupt cannot be enabled.
|
||||
*/
|
||||
int omap_irq_enable_vblank(struct drm_device *dev, int crtc)
|
||||
int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id)
|
||||
{
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
struct drm_crtc *crtc = priv->crtcs[crtc_id];
|
||||
unsigned long flags;
|
||||
|
||||
DBG("dev=%p, crtc=%d", dev, crtc);
|
||||
DBG("dev=%p, crtc=%d", dev, crtc_id);
|
||||
|
||||
dispc_runtime_get();
|
||||
spin_lock_irqsave(&list_lock, flags);
|
||||
|
@ -156,12 +157,13 @@ int omap_irq_enable_vblank(struct drm_device *dev, int crtc)
|
|||
* a hardware vblank counter, this routine should be a no-op, since
|
||||
* interrupts will have to stay on to keep the count accurate.
|
||||
*/
|
||||
void omap_irq_disable_vblank(struct drm_device *dev, int crtc)
|
||||
void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id)
|
||||
{
|
||||
struct omap_drm_private *priv = dev->dev_private;
|
||||
struct drm_crtc *crtc = priv->crtcs[crtc_id];
|
||||
unsigned long flags;
|
||||
|
||||
DBG("dev=%p, crtc=%d", dev, crtc);
|
||||
DBG("dev=%p, crtc=%d", dev, crtc_id);
|
||||
|
||||
dispc_runtime_get();
|
||||
spin_lock_irqsave(&list_lock, flags);
|
||||
|
@ -186,9 +188,12 @@ irqreturn_t omap_irq_handler(DRM_IRQ_ARGS)
|
|||
|
||||
VERB("irqs: %08x", irqstatus);
|
||||
|
||||
for (id = 0; id < priv->num_crtcs; id++)
|
||||
if (irqstatus & pipe2vbl(id))
|
||||
for (id = 0; id < priv->num_crtcs; id++) {
|
||||
struct drm_crtc *crtc = priv->crtcs[id];
|
||||
|
||||
if (irqstatus & pipe2vbl(crtc))
|
||||
drm_handle_vblank(dev, id);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&list_lock, flags);
|
||||
list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
|
||||
|
|
|
@ -247,6 +247,12 @@ static int omap_plane_update(struct drm_plane *plane,
|
|||
{
|
||||
struct omap_plane *omap_plane = to_omap_plane(plane);
|
||||
omap_plane->enabled = true;
|
||||
|
||||
if (plane->fb)
|
||||
drm_framebuffer_unreference(plane->fb);
|
||||
|
||||
drm_framebuffer_reference(fb);
|
||||
|
||||
return omap_plane_mode_set(plane, crtc, fb,
|
||||
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||
src_x, src_y, src_w, src_h,
|
||||
|
|
|
@ -29,8 +29,10 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#define MIPID_CMD_READ_DISP_ID 0x04
|
||||
#define MIPID_CMD_READ_RED 0x06
|
||||
|
@ -336,8 +338,6 @@ static int acx565akm_bl_update_status(struct backlight_device *dev)
|
|||
r = 0;
|
||||
if (md->has_bc)
|
||||
acx565akm_set_brightness(md, level);
|
||||
else if (md->dssdev->set_backlight)
|
||||
r = md->dssdev->set_backlight(md->dssdev, level);
|
||||
else
|
||||
r = -ENODEV;
|
||||
|
||||
|
@ -352,7 +352,7 @@ static int acx565akm_bl_get_intensity(struct backlight_device *dev)
|
|||
|
||||
dev_dbg(&dev->dev, "%s\n", __func__);
|
||||
|
||||
if (!md->has_bc && md->dssdev->set_backlight == NULL)
|
||||
if (!md->has_bc)
|
||||
return -ENODEV;
|
||||
|
||||
if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
|
||||
|
@ -496,21 +496,38 @@ static struct omap_video_timings acx_panel_timings = {
|
|||
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
|
||||
};
|
||||
|
||||
static struct panel_acx565akm_data *get_panel_data(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return (struct panel_acx565akm_data *) dssdev->data;
|
||||
}
|
||||
|
||||
static int acx_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
struct acx565akm_device *md = &acx_dev;
|
||||
struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
|
||||
struct backlight_device *bldev;
|
||||
int max_brightness, brightness;
|
||||
struct backlight_properties props;
|
||||
|
||||
dev_dbg(&dssdev->dev, "%s\n", __func__);
|
||||
|
||||
if (!panel_data)
|
||||
return -EINVAL;
|
||||
|
||||
/* FIXME AC bias ? */
|
||||
dssdev->panel.timings = acx_panel_timings;
|
||||
|
||||
if (dssdev->platform_enable)
|
||||
dssdev->platform_enable(dssdev);
|
||||
if (gpio_is_valid(panel_data->reset_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, panel_data->reset_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "lcd reset");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_set_value(panel_data->reset_gpio, 1);
|
||||
|
||||
/*
|
||||
* After reset we have to wait 5 msec before the first
|
||||
* command can be sent.
|
||||
|
@ -522,8 +539,9 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
|
|||
r = panel_detect(md);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "%s panel detect error\n", __func__);
|
||||
if (!md->enabled && dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
if (!md->enabled && gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_set_value(panel_data->reset_gpio, 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -532,8 +550,8 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
|
|||
mutex_unlock(&acx_dev.mutex);
|
||||
|
||||
if (!md->enabled) {
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_set_value(panel_data->reset_gpio, 0);
|
||||
}
|
||||
|
||||
/*------- Backlight control --------*/
|
||||
|
@ -557,15 +575,10 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
|
|||
md->cabc_mode = get_hw_cabc_mode(md);
|
||||
}
|
||||
|
||||
if (md->has_bc)
|
||||
max_brightness = 255;
|
||||
else
|
||||
max_brightness = dssdev->max_backlight_level;
|
||||
max_brightness = 255;
|
||||
|
||||
if (md->has_bc)
|
||||
brightness = acx565akm_get_actual_brightness(md);
|
||||
else if (dssdev->get_backlight)
|
||||
brightness = dssdev->get_backlight(dssdev);
|
||||
else
|
||||
brightness = 0;
|
||||
|
||||
|
@ -591,6 +604,7 @@ static void acx_panel_remove(struct omap_dss_device *dssdev)
|
|||
static int acx_panel_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct acx565akm_device *md = &acx_dev;
|
||||
struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "%s\n", __func__);
|
||||
|
@ -612,11 +626,8 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
|
|||
/*FIXME tweak me */
|
||||
msleep(50);
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto fail;
|
||||
}
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_set_value(panel_data->reset_gpio, 1);
|
||||
|
||||
if (md->enabled) {
|
||||
dev_dbg(&md->spi->dev, "panel already enabled\n");
|
||||
|
@ -645,8 +656,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
|
|||
mutex_unlock(&md->mutex);
|
||||
|
||||
return acx565akm_bl_update_status(md->bl_dev);
|
||||
fail:
|
||||
omapdss_sdi_display_disable(dssdev);
|
||||
|
||||
fail_unlock:
|
||||
mutex_unlock(&md->mutex);
|
||||
return r;
|
||||
|
@ -655,6 +665,7 @@ fail_unlock:
|
|||
static void acx_panel_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct acx565akm_device *md = &acx_dev;
|
||||
struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
|
||||
|
||||
dev_dbg(&dssdev->dev, "%s\n", __func__);
|
||||
|
||||
|
@ -678,8 +689,8 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev)
|
|||
*/
|
||||
msleep(50);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_set_value(panel_data->reset_gpio, 0);
|
||||
|
||||
/* FIXME need to tweak this delay */
|
||||
msleep(100);
|
||||
|
|
|
@ -33,9 +33,10 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include <video/omap-panel-generic-dpi.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
struct panel_config {
|
||||
struct omap_video_timings timings;
|
||||
|
@ -533,7 +534,7 @@ static inline struct panel_generic_dpi_data
|
|||
|
||||
static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
int r, i;
|
||||
struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
struct panel_config *panel_config = drv_data->panel_config;
|
||||
|
@ -552,15 +553,13 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
|
|||
if (panel_config->power_on_delay)
|
||||
msleep(panel_config->power_on_delay);
|
||||
|
||||
if (panel_data->platform_enable) {
|
||||
r = panel_data->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
for (i = 0; i < panel_data->num_gpios; ++i) {
|
||||
gpio_set_value_cansleep(panel_data->gpios[i],
|
||||
panel_data->gpio_invert[i] ? 0 : 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
@ -570,12 +569,15 @@ static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev)
|
|||
struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
struct panel_config *panel_config = drv_data->panel_config;
|
||||
int i;
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return;
|
||||
|
||||
if (panel_data->platform_disable)
|
||||
panel_data->platform_disable(dssdev);
|
||||
for (i = panel_data->num_gpios - 1; i >= 0; --i) {
|
||||
gpio_set_value_cansleep(panel_data->gpios[i],
|
||||
panel_data->gpio_invert[i] ? 1 : 0);
|
||||
}
|
||||
|
||||
/* wait couple of vsyncs after disabling the LCD */
|
||||
if (panel_config->power_off_delay)
|
||||
|
@ -589,7 +591,7 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
|
|||
struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
|
||||
struct panel_config *panel_config = NULL;
|
||||
struct panel_drv_data *drv_data = NULL;
|
||||
int i;
|
||||
int i, r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "probe\n");
|
||||
|
||||
|
@ -606,9 +608,18 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
|
|||
if (!panel_config)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < panel_data->num_gpios; ++i) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, panel_data->gpios[i],
|
||||
panel_data->gpio_invert[i] ?
|
||||
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
|
||||
"panel gpio");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
dssdev->panel.timings = panel_config->timings;
|
||||
|
||||
drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
|
||||
drv_data = devm_kzalloc(&dssdev->dev, sizeof(*drv_data), GFP_KERNEL);
|
||||
if (!drv_data)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -624,12 +635,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
|
|||
|
||||
static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
dev_dbg(&dssdev->dev, "remove\n");
|
||||
|
||||
kfree(drv_data);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,10 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
struct lb035q02_data {
|
||||
struct mutex lock;
|
||||
|
@ -48,9 +50,16 @@ static struct omap_video_timings lb035q02_timings = {
|
|||
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
|
||||
};
|
||||
|
||||
static inline struct panel_generic_dpi_data
|
||||
*get_panel_data(const struct omap_dss_device *dssdev)
|
||||
{
|
||||
return (struct panel_generic_dpi_data *) dssdev->data;
|
||||
}
|
||||
|
||||
static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
|
||||
int r, i;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
@ -62,54 +71,65 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err0;
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
for (i = 0; i < panel_data->num_gpios; ++i) {
|
||||
gpio_set_value_cansleep(panel_data->gpios[i],
|
||||
panel_data->gpio_invert[i] ? 0 : 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void lb035q02_panel_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
|
||||
int i;
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return;
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
for (i = panel_data->num_gpios - 1; i >= 0; --i) {
|
||||
gpio_set_value_cansleep(panel_data->gpios[i],
|
||||
panel_data->gpio_invert[i] ? 1 : 0);
|
||||
}
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
static int lb035q02_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
|
||||
struct lb035q02_data *ld;
|
||||
int r;
|
||||
int r, i;
|
||||
|
||||
if (!panel_data)
|
||||
return -EINVAL;
|
||||
|
||||
dssdev->panel.timings = lb035q02_timings;
|
||||
|
||||
ld = kzalloc(sizeof(*ld), GFP_KERNEL);
|
||||
if (!ld) {
|
||||
r = -ENOMEM;
|
||||
goto err;
|
||||
ld = devm_kzalloc(&dssdev->dev, sizeof(*ld), GFP_KERNEL);
|
||||
if (!ld)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < panel_data->num_gpios; ++i) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, panel_data->gpios[i],
|
||||
panel_data->gpio_invert[i] ?
|
||||
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
|
||||
"panel gpio");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
mutex_init(&ld->lock);
|
||||
dev_set_drvdata(&dssdev->dev, ld);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void lb035q02_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
kfree(ld);
|
||||
}
|
||||
|
||||
static int lb035q02_panel_enable(struct omap_dss_device *dssdev)
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-n8x0.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#define BLIZZARD_REV_CODE 0x00
|
||||
#define BLIZZARD_CONFIG 0x02
|
||||
|
@ -69,7 +68,6 @@ static struct panel_drv_data {
|
|||
|
||||
struct omap_dss_device *dssdev;
|
||||
struct spi_device *spidev;
|
||||
struct backlight_device *bldev;
|
||||
|
||||
int blizzard_ver;
|
||||
} s_drv_data;
|
||||
|
@ -297,12 +295,6 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
|
|||
|
||||
gpio_direction_output(bdata->ctrl_pwrdown, 1);
|
||||
|
||||
if (bdata->platform_enable) {
|
||||
r = bdata->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err_plat_en;
|
||||
}
|
||||
|
||||
omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res);
|
||||
omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
|
||||
|
@ -375,9 +367,6 @@ err_inv_panel:
|
|||
err_inv_chip:
|
||||
omapdss_rfbi_display_disable(dssdev);
|
||||
err_rfbi_en:
|
||||
if (bdata->platform_disable)
|
||||
bdata->platform_disable(dssdev);
|
||||
err_plat_en:
|
||||
gpio_direction_output(bdata->ctrl_pwrdown, 0);
|
||||
return r;
|
||||
}
|
||||
|
@ -394,9 +383,6 @@ static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
|
|||
send_display_off(spi);
|
||||
send_sleep_in(spi);
|
||||
|
||||
if (bdata->platform_disable)
|
||||
bdata->platform_disable(dssdev);
|
||||
|
||||
/*
|
||||
* HACK: we should turn off the panel here, but there is some problem
|
||||
* with the initialization sequence, and we fail to init the panel if we
|
||||
|
@ -424,54 +410,10 @@ static const struct rfbi_timings n8x0_panel_timings = {
|
|||
.cs_pulse_width = 0,
|
||||
};
|
||||
|
||||
static int n8x0_bl_update_status(struct backlight_device *dev)
|
||||
{
|
||||
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
|
||||
struct panel_n8x0_data *bdata = get_board_data(dssdev);
|
||||
struct panel_drv_data *ddata = get_drv_data(dssdev);
|
||||
int r;
|
||||
int level;
|
||||
|
||||
mutex_lock(&ddata->lock);
|
||||
|
||||
if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
|
||||
dev->props.power == FB_BLANK_UNBLANK)
|
||||
level = dev->props.brightness;
|
||||
else
|
||||
level = 0;
|
||||
|
||||
dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
|
||||
|
||||
if (!bdata->set_backlight)
|
||||
r = -EINVAL;
|
||||
else
|
||||
r = bdata->set_backlight(dssdev, level);
|
||||
|
||||
mutex_unlock(&ddata->lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int n8x0_bl_get_intensity(struct backlight_device *dev)
|
||||
{
|
||||
if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
|
||||
dev->props.power == FB_BLANK_UNBLANK)
|
||||
return dev->props.brightness;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops n8x0_bl_ops = {
|
||||
.get_brightness = n8x0_bl_get_intensity,
|
||||
.update_status = n8x0_bl_update_status,
|
||||
};
|
||||
|
||||
static int n8x0_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_n8x0_data *bdata = get_board_data(dssdev);
|
||||
struct panel_drv_data *ddata;
|
||||
struct backlight_device *bldev;
|
||||
struct backlight_properties props;
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "probe\n");
|
||||
|
@ -491,40 +433,27 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
|
|||
dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.max_brightness = 127;
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
|
||||
dssdev, &n8x0_bl_ops, &props);
|
||||
if (IS_ERR(bldev)) {
|
||||
r = PTR_ERR(bldev);
|
||||
dev_err(&dssdev->dev, "register backlight failed\n");
|
||||
return r;
|
||||
if (gpio_is_valid(bdata->panel_reset)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, bdata->panel_reset,
|
||||
GPIOF_OUT_INIT_LOW, "PANEL RESET");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
ddata->bldev = bldev;
|
||||
|
||||
bldev->props.fb_blank = FB_BLANK_UNBLANK;
|
||||
bldev->props.power = FB_BLANK_UNBLANK;
|
||||
bldev->props.brightness = 127;
|
||||
|
||||
n8x0_bl_update_status(bldev);
|
||||
if (gpio_is_valid(bdata->ctrl_pwrdown)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, bdata->ctrl_pwrdown,
|
||||
GPIOF_OUT_INIT_LOW, "PANEL PWRDOWN");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void n8x0_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = get_drv_data(dssdev);
|
||||
struct backlight_device *bldev;
|
||||
|
||||
dev_dbg(&dssdev->dev, "remove\n");
|
||||
|
||||
bldev = ddata->bldev;
|
||||
bldev->props.power = FB_BLANK_POWERDOWN;
|
||||
n8x0_bl_update_status(bldev);
|
||||
backlight_device_unregister(bldev);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,10 +19,11 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#define LCD_XRES 800
|
||||
#define LCD_YRES 480
|
||||
|
@ -32,10 +33,6 @@
|
|||
*/
|
||||
#define LCD_PIXEL_CLOCK 23800
|
||||
|
||||
struct nec_8048_data {
|
||||
struct backlight_device *bl;
|
||||
};
|
||||
|
||||
static const struct {
|
||||
unsigned char addr;
|
||||
unsigned char dat;
|
||||
|
@ -84,93 +81,47 @@ static struct omap_video_timings nec_8048_panel_timings = {
|
|||
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
|
||||
};
|
||||
|
||||
static int nec_8048_bl_update_status(struct backlight_device *bl)
|
||||
static inline struct panel_nec_nl8048_data
|
||||
*get_panel_data(const struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
|
||||
int level;
|
||||
|
||||
if (!dssdev->set_backlight)
|
||||
return -EINVAL;
|
||||
|
||||
if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
|
||||
bl->props.power == FB_BLANK_UNBLANK)
|
||||
level = bl->props.brightness;
|
||||
else
|
||||
level = 0;
|
||||
|
||||
return dssdev->set_backlight(dssdev, level);
|
||||
return (struct panel_nec_nl8048_data *) dssdev->data;
|
||||
}
|
||||
|
||||
static int nec_8048_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
|
||||
bl->props.power == FB_BLANK_UNBLANK)
|
||||
return bl->props.brightness;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops nec_8048_bl_ops = {
|
||||
.get_brightness = nec_8048_bl_get_brightness,
|
||||
.update_status = nec_8048_bl_update_status,
|
||||
};
|
||||
|
||||
static int nec_8048_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct backlight_device *bl;
|
||||
struct nec_8048_data *necd;
|
||||
struct backlight_properties props;
|
||||
struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
if (!pd)
|
||||
return -EINVAL;
|
||||
|
||||
dssdev->panel.timings = nec_8048_panel_timings;
|
||||
|
||||
necd = kzalloc(sizeof(*necd), GFP_KERNEL);
|
||||
if (!necd)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, necd);
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = 255;
|
||||
|
||||
bl = backlight_device_register("nec-8048", &dssdev->dev, dssdev,
|
||||
&nec_8048_bl_ops, &props);
|
||||
if (IS_ERR(bl)) {
|
||||
r = PTR_ERR(bl);
|
||||
kfree(necd);
|
||||
return r;
|
||||
if (gpio_is_valid(pd->qvga_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, pd->qvga_gpio,
|
||||
GPIOF_OUT_INIT_HIGH, "lcd QVGA");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
necd->bl = bl;
|
||||
|
||||
bl->props.fb_blank = FB_BLANK_UNBLANK;
|
||||
bl->props.power = FB_BLANK_UNBLANK;
|
||||
bl->props.max_brightness = dssdev->max_backlight_level;
|
||||
bl->props.brightness = dssdev->max_backlight_level;
|
||||
|
||||
r = nec_8048_bl_update_status(bl);
|
||||
if (r < 0)
|
||||
dev_err(&dssdev->dev, "failed to set lcd brightness\n");
|
||||
if (gpio_is_valid(pd->res_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, pd->res_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "lcd RES");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
|
||||
struct backlight_device *bl = necd->bl;
|
||||
|
||||
bl->props.power = FB_BLANK_POWERDOWN;
|
||||
nec_8048_bl_update_status(bl);
|
||||
backlight_device_unregister(bl);
|
||||
|
||||
kfree(necd);
|
||||
}
|
||||
|
||||
static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
|
||||
int r;
|
||||
struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
|
||||
struct backlight_device *bl = necd->bl;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
@ -182,36 +133,24 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err0;
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
r = nec_8048_bl_update_status(bl);
|
||||
if (r < 0)
|
||||
dev_err(&dssdev->dev, "failed to set lcd brightness\n");
|
||||
if (gpio_is_valid(pd->res_gpio))
|
||||
gpio_set_value_cansleep(pd->res_gpio, 1);
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void nec_8048_panel_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
|
||||
struct backlight_device *bl = necd->bl;
|
||||
struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return;
|
||||
|
||||
bl->props.brightness = 0;
|
||||
nec_8048_bl_update_status(bl);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
if (gpio_is_valid(pd->res_gpio))
|
||||
gpio_set_value_cansleep(pd->res_gpio, 0);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
@ -303,16 +242,22 @@ static int nec_8048_spi_remove(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nec_8048_spi_suspend(struct spi_device *spi, pm_message_t mesg)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static int nec_8048_spi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
|
||||
nec_8048_spi_send(spi, 2, 0x01);
|
||||
mdelay(40);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nec_8048_spi_resume(struct spi_device *spi)
|
||||
static int nec_8048_spi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
|
||||
/* reinitialize the panel */
|
||||
spi_setup(spi);
|
||||
nec_8048_spi_send(spi, 2, 0x00);
|
||||
|
@ -321,14 +266,20 @@ static int nec_8048_spi_resume(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(nec_8048_spi_pm_ops, nec_8048_spi_suspend,
|
||||
nec_8048_spi_resume);
|
||||
#define NEC_8048_SPI_PM_OPS (&nec_8048_spi_pm_ops)
|
||||
#else
|
||||
#define NEC_8048_SPI_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static struct spi_driver nec_8048_spi_driver = {
|
||||
.probe = nec_8048_spi_probe,
|
||||
.remove = nec_8048_spi_remove,
|
||||
.suspend = nec_8048_spi_suspend,
|
||||
.resume = nec_8048_spi_resume,
|
||||
.driver = {
|
||||
.name = "nec_8048_spi",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = NEC_8048_SPI_PM_OPS,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <linux/gpio.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-picodlp.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#include "panel-picodlp.h"
|
||||
|
||||
|
@ -354,12 +354,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
|
|||
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
|
||||
struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
|
||||
msleep(1);
|
||||
gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
|
||||
|
@ -398,9 +392,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
|
|||
err:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
err1:
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -412,9 +403,6 @@ static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
|
|||
|
||||
gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
|
||||
gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
}
|
||||
|
||||
static int picodlp_panel_probe(struct omap_dss_device *dssdev)
|
||||
|
@ -423,11 +411,14 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev)
|
|||
struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_client *picodlp_i2c_client;
|
||||
int r = 0, picodlp_adapter_id;
|
||||
int r, picodlp_adapter_id;
|
||||
|
||||
dssdev->panel.timings = pico_ls_timings;
|
||||
|
||||
picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
|
||||
if (!picodlp_pdata)
|
||||
return -EINVAL;
|
||||
|
||||
picod = devm_kzalloc(&dssdev->dev, sizeof(*picod), GFP_KERNEL);
|
||||
if (!picod)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -438,25 +429,37 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev)
|
|||
adapter = i2c_get_adapter(picodlp_adapter_id);
|
||||
if (!adapter) {
|
||||
dev_err(&dssdev->dev, "can't get i2c adapter\n");
|
||||
r = -ENODEV;
|
||||
goto err;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
|
||||
if (!picodlp_i2c_client) {
|
||||
dev_err(&dssdev->dev, "can't add i2c device::"
|
||||
" picodlp_i2c_client is NULL\n");
|
||||
r = -ENODEV;
|
||||
goto err;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
picod->picodlp_i2c_client = picodlp_i2c_client;
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, picod);
|
||||
return r;
|
||||
err:
|
||||
kfree(picod);
|
||||
return r;
|
||||
|
||||
if (gpio_is_valid(picodlp_pdata->emu_done_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev,
|
||||
picodlp_pdata->emu_done_gpio,
|
||||
GPIOF_IN, "DLP EMU DONE");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(picodlp_pdata->pwrgood_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev,
|
||||
picodlp_pdata->pwrgood_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "DLP PWRGOOD");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void picodlp_panel_remove(struct omap_dss_device *dssdev)
|
||||
|
|
|
@ -20,16 +20,13 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
struct sharp_data {
|
||||
struct backlight_device *bl;
|
||||
};
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
static struct omap_video_timings sharp_ls_timings = {
|
||||
.x_res = 480,
|
||||
|
@ -52,91 +49,67 @@ static struct omap_video_timings sharp_ls_timings = {
|
|||
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
|
||||
};
|
||||
|
||||
static int sharp_ls_bl_update_status(struct backlight_device *bl)
|
||||
static inline struct panel_sharp_ls037v7dw01_data
|
||||
*get_panel_data(const struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
|
||||
int level;
|
||||
|
||||
if (!dssdev->set_backlight)
|
||||
return -EINVAL;
|
||||
|
||||
if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
|
||||
bl->props.power == FB_BLANK_UNBLANK)
|
||||
level = bl->props.brightness;
|
||||
else
|
||||
level = 0;
|
||||
|
||||
return dssdev->set_backlight(dssdev, level);
|
||||
return (struct panel_sharp_ls037v7dw01_data *) dssdev->data;
|
||||
}
|
||||
|
||||
static int sharp_ls_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
|
||||
bl->props.power == FB_BLANK_UNBLANK)
|
||||
return bl->props.brightness;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops sharp_ls_bl_ops = {
|
||||
.get_brightness = sharp_ls_bl_get_brightness,
|
||||
.update_status = sharp_ls_bl_update_status,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct backlight_device *bl;
|
||||
struct sharp_data *sd;
|
||||
struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
if (!pd)
|
||||
return -EINVAL;
|
||||
|
||||
dssdev->panel.timings = sharp_ls_timings;
|
||||
|
||||
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
|
||||
if (!sd)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, sd);
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = dssdev->max_backlight_level;
|
||||
props.type = BACKLIGHT_RAW;
|
||||
|
||||
bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
|
||||
&sharp_ls_bl_ops, &props);
|
||||
if (IS_ERR(bl)) {
|
||||
r = PTR_ERR(bl);
|
||||
kfree(sd);
|
||||
return r;
|
||||
if (gpio_is_valid(pd->mo_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, pd->mo_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "lcd MO");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
sd->bl = bl;
|
||||
|
||||
bl->props.fb_blank = FB_BLANK_UNBLANK;
|
||||
bl->props.power = FB_BLANK_UNBLANK;
|
||||
bl->props.brightness = dssdev->max_backlight_level;
|
||||
r = sharp_ls_bl_update_status(bl);
|
||||
if (r < 0)
|
||||
dev_err(&dssdev->dev, "failed to set lcd brightness\n");
|
||||
if (gpio_is_valid(pd->lr_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, pd->lr_gpio,
|
||||
GPIOF_OUT_INIT_HIGH, "lcd LR");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pd->ud_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, pd->ud_gpio,
|
||||
GPIOF_OUT_INIT_HIGH, "lcd UD");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pd->resb_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, pd->resb_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "lcd RESB");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pd->ini_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, pd->ini_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "lcd INI");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
|
||||
struct backlight_device *bl = sd->bl;
|
||||
|
||||
bl->props.power = FB_BLANK_POWERDOWN;
|
||||
sharp_ls_bl_update_status(bl);
|
||||
backlight_device_unregister(bl);
|
||||
|
||||
kfree(sd);
|
||||
}
|
||||
|
||||
static int sharp_ls_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
|
||||
int r = 0;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
|
@ -152,26 +125,29 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
|
|||
/* wait couple of vsyncs until enabling the LCD */
|
||||
msleep(50);
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
if (gpio_is_valid(pd->resb_gpio))
|
||||
gpio_set_value_cansleep(pd->resb_gpio, 1);
|
||||
|
||||
if (gpio_is_valid(pd->ini_gpio))
|
||||
gpio_set_value_cansleep(pd->ini_gpio, 1);
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void sharp_ls_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return;
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
if (gpio_is_valid(pd->ini_gpio))
|
||||
gpio_set_value_cansleep(pd->ini_gpio, 0);
|
||||
|
||||
if (gpio_is_valid(pd->resb_gpio))
|
||||
gpio_set_value_cansleep(pd->resb_gpio, 0);
|
||||
|
||||
/* wait at least 5 vsyncs after disabling the LCD */
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <linux/mutex.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-nokia-dsi.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
/* DSI Virtual channel. Hardcoded for now. */
|
||||
|
@ -54,61 +54,6 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
|
|||
|
||||
static int taal_panel_reset(struct omap_dss_device *dssdev);
|
||||
|
||||
/**
|
||||
* struct panel_config - panel configuration
|
||||
* @name: panel name
|
||||
* @type: panel type
|
||||
* @timings: panel resolution
|
||||
* @sleep: various panel specific delays, passed to msleep() if non-zero
|
||||
* @reset_sequence: reset sequence timings, passed to udelay() if non-zero
|
||||
* @regulators: array of panel regulators
|
||||
* @num_regulators: number of regulators in the array
|
||||
*/
|
||||
struct panel_config {
|
||||
const char *name;
|
||||
int type;
|
||||
|
||||
struct omap_video_timings timings;
|
||||
|
||||
struct {
|
||||
unsigned int sleep_in;
|
||||
unsigned int sleep_out;
|
||||
unsigned int hw_reset;
|
||||
unsigned int enable_te;
|
||||
} sleep;
|
||||
|
||||
struct {
|
||||
unsigned int high;
|
||||
unsigned int low;
|
||||
} reset_sequence;
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
PANEL_TAAL,
|
||||
};
|
||||
|
||||
static struct panel_config panel_configs[] = {
|
||||
{
|
||||
.name = "taal",
|
||||
.type = PANEL_TAAL,
|
||||
.timings = {
|
||||
.x_res = 864,
|
||||
.y_res = 480,
|
||||
},
|
||||
.sleep = {
|
||||
.sleep_in = 5,
|
||||
.sleep_out = 5,
|
||||
.hw_reset = 5,
|
||||
.enable_te = 100, /* possible panel bug */
|
||||
},
|
||||
.reset_sequence = {
|
||||
.high = 10,
|
||||
.low = 10,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
struct taal_data {
|
||||
struct mutex lock;
|
||||
|
||||
|
@ -121,9 +66,6 @@ struct taal_data {
|
|||
|
||||
struct omap_dss_device *dssdev;
|
||||
|
||||
/* panel specific HW info */
|
||||
struct panel_config *panel_config;
|
||||
|
||||
/* panel HW configuration from DT or platform data */
|
||||
int reset_gpio;
|
||||
int ext_te_gpio;
|
||||
|
@ -134,8 +76,6 @@ struct taal_data {
|
|||
|
||||
/* runtime variables */
|
||||
bool enabled;
|
||||
u8 rotate;
|
||||
bool mirror;
|
||||
|
||||
bool te_enabled;
|
||||
|
||||
|
@ -221,8 +161,7 @@ static int taal_sleep_in(struct taal_data *td)
|
|||
|
||||
hw_guard_start(td, 120);
|
||||
|
||||
if (td->panel_config->sleep.sleep_in)
|
||||
msleep(td->panel_config->sleep.sleep_in);
|
||||
msleep(5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -239,8 +178,7 @@ static int taal_sleep_out(struct taal_data *td)
|
|||
|
||||
hw_guard_start(td, 120);
|
||||
|
||||
if (td->panel_config->sleep.sleep_out)
|
||||
msleep(td->panel_config->sleep.sleep_out);
|
||||
msleep(5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -262,49 +200,6 @@ static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
|
||||
{
|
||||
int r;
|
||||
u8 mode;
|
||||
int b5, b6, b7;
|
||||
|
||||
r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
switch (rotate) {
|
||||
default:
|
||||
case 0:
|
||||
b7 = 0;
|
||||
b6 = 0;
|
||||
b5 = 0;
|
||||
break;
|
||||
case 1:
|
||||
b7 = 0;
|
||||
b6 = 1;
|
||||
b5 = 1;
|
||||
break;
|
||||
case 2:
|
||||
b7 = 1;
|
||||
b6 = 1;
|
||||
b5 = 0;
|
||||
break;
|
||||
case 3:
|
||||
b7 = 1;
|
||||
b6 = 0;
|
||||
b5 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mirror)
|
||||
b6 = !b6;
|
||||
|
||||
mode &= ~((1<<7) | (1<<6) | (1<<5));
|
||||
mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
|
||||
|
||||
return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
|
||||
}
|
||||
|
||||
static int taal_set_update_window(struct taal_data *td,
|
||||
u16 x, u16 y, u16 w, u16 h)
|
||||
{
|
||||
|
@ -515,15 +410,8 @@ static const struct backlight_ops taal_bl_ops = {
|
|||
static void taal_get_resolution(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
if (td->rotate == 0 || td->rotate == 2) {
|
||||
*xres = dssdev->panel.timings.x_res;
|
||||
*yres = dssdev->panel.timings.y_res;
|
||||
} else {
|
||||
*yres = dssdev->panel.timings.x_res;
|
||||
*xres = dssdev->panel.timings.y_res;
|
||||
}
|
||||
*xres = dssdev->panel.timings.x_res;
|
||||
*yres = dssdev->panel.timings.y_res;
|
||||
}
|
||||
|
||||
static ssize_t taal_num_errors_show(struct device *dev,
|
||||
|
@ -845,17 +733,14 @@ static void taal_hw_reset(struct omap_dss_device *dssdev)
|
|||
return;
|
||||
|
||||
gpio_set_value(td->reset_gpio, 1);
|
||||
if (td->panel_config->reset_sequence.high)
|
||||
udelay(td->panel_config->reset_sequence.high);
|
||||
udelay(10);
|
||||
/* reset the panel */
|
||||
gpio_set_value(td->reset_gpio, 0);
|
||||
/* assert reset */
|
||||
if (td->panel_config->reset_sequence.low)
|
||||
udelay(td->panel_config->reset_sequence.low);
|
||||
udelay(10);
|
||||
gpio_set_value(td->reset_gpio, 1);
|
||||
/* wait after releasing reset */
|
||||
if (td->panel_config->sleep.hw_reset)
|
||||
msleep(td->panel_config->sleep.hw_reset);
|
||||
msleep(5);
|
||||
}
|
||||
|
||||
static void taal_probe_pdata(struct taal_data *td,
|
||||
|
@ -881,8 +766,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
struct backlight_properties props;
|
||||
struct taal_data *td;
|
||||
struct backlight_device *bldev = NULL;
|
||||
int r, i;
|
||||
const char *panel_name;
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "probe\n");
|
||||
|
||||
|
@ -897,26 +781,13 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
const struct nokia_dsi_panel_data *pdata = dssdev->data;
|
||||
|
||||
taal_probe_pdata(td, pdata);
|
||||
|
||||
panel_name = pdata->name;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (panel_name == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
|
||||
if (strcmp(panel_name, panel_configs[i].name) == 0) {
|
||||
td->panel_config = &panel_configs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!td->panel_config)
|
||||
return -EINVAL;
|
||||
|
||||
dssdev->panel.timings = td->panel_config->timings;
|
||||
dssdev->panel.timings.x_res = 864;
|
||||
dssdev->panel.timings.y_res = 480;
|
||||
dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
|
||||
dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
|
||||
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
|
||||
|
@ -1049,6 +920,15 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
u8 id1, id2, id3;
|
||||
int r;
|
||||
struct omap_dss_dsi_config dsi_config = {
|
||||
.mode = OMAP_DSS_DSI_CMD_MODE,
|
||||
.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
|
||||
.timings = &dssdev->panel.timings,
|
||||
.hs_clk_min = 150000000,
|
||||
.hs_clk_max = 300000000,
|
||||
.lp_clk_min = 7000000,
|
||||
.lp_clk_max = 10000000,
|
||||
};
|
||||
|
||||
r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
|
||||
if (r) {
|
||||
|
@ -1056,14 +936,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
goto err0;
|
||||
};
|
||||
|
||||
omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res);
|
||||
omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
|
||||
omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
|
||||
|
||||
r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
|
||||
r = omapdss_dsi_set_config(dssdev, &dsi_config);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
|
||||
dev_err(&dssdev->dev, "failed to configure DSI\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
|
@ -1086,8 +961,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
goto err;
|
||||
|
||||
/* on early Taal revisions CABC is broken */
|
||||
if (td->panel_config->type == PANEL_TAAL &&
|
||||
(id2 == 0x00 || id2 == 0xff || id2 == 0x81))
|
||||
if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
|
||||
td->cabc_broken = true;
|
||||
|
||||
r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff);
|
||||
|
@ -1104,10 +978,6 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
r = taal_set_addr_mode(td, td->rotate, td->mirror);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
if (!td->cabc_broken) {
|
||||
r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode);
|
||||
if (r)
|
||||
|
@ -1129,8 +999,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
td->enabled = 1;
|
||||
|
||||
if (!td->intro_printed) {
|
||||
dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n",
|
||||
td->panel_config->name, id1, id2, id3);
|
||||
dev_info(&dssdev->dev, "panel revision %02x.%02x.%02x\n",
|
||||
id1, id2, id3);
|
||||
if (td->cabc_broken)
|
||||
dev_info(&dssdev->dev,
|
||||
"old Taal version, CABC disabled\n");
|
||||
|
@ -1311,8 +1181,8 @@ static int taal_update(struct omap_dss_device *dssdev,
|
|||
|
||||
/* XXX no need to send this every frame, but dsi break if not done */
|
||||
r = taal_set_update_window(td, 0, 0,
|
||||
td->panel_config->timings.x_res,
|
||||
td->panel_config->timings.y_res);
|
||||
dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
|
@ -1365,8 +1235,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
|||
if (!gpio_is_valid(td->ext_te_gpio))
|
||||
omapdss_dsi_enable_te(dssdev, enable);
|
||||
|
||||
if (td->panel_config->sleep.enable_te)
|
||||
msleep(td->panel_config->sleep.enable_te);
|
||||
/* possible panel bug */
|
||||
msleep(100);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -1419,112 +1289,6 @@ static int taal_get_te(struct omap_dss_device *dssdev)
|
|||
return r;
|
||||
}
|
||||
|
||||
static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
u16 dw, dh;
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->rotate == rotate)
|
||||
goto end;
|
||||
|
||||
dsi_bus_lock(dssdev);
|
||||
|
||||
if (td->enabled) {
|
||||
r = taal_wake_up(dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = taal_set_addr_mode(td, rotate, td->mirror);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rotate == 0 || rotate == 2) {
|
||||
dw = dssdev->panel.timings.x_res;
|
||||
dh = dssdev->panel.timings.y_res;
|
||||
} else {
|
||||
dw = dssdev->panel.timings.y_res;
|
||||
dh = dssdev->panel.timings.x_res;
|
||||
}
|
||||
|
||||
omapdss_dsi_set_size(dssdev, dw, dh);
|
||||
|
||||
td->rotate = rotate;
|
||||
|
||||
dsi_bus_unlock(dssdev);
|
||||
end:
|
||||
mutex_unlock(&td->lock);
|
||||
return 0;
|
||||
err:
|
||||
dsi_bus_unlock(dssdev);
|
||||
mutex_unlock(&td->lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
static u8 taal_get_rotate(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
r = td->rotate;
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "mirror %d\n", enable);
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->mirror == enable)
|
||||
goto end;
|
||||
|
||||
dsi_bus_lock(dssdev);
|
||||
if (td->enabled) {
|
||||
r = taal_wake_up(dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = taal_set_addr_mode(td, td->rotate, enable);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
td->mirror = enable;
|
||||
|
||||
dsi_bus_unlock(dssdev);
|
||||
end:
|
||||
mutex_unlock(&td->lock);
|
||||
return 0;
|
||||
err:
|
||||
dsi_bus_unlock(dssdev);
|
||||
mutex_unlock(&td->lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool taal_get_mirror(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
r = td->mirror;
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
|
@ -1758,10 +1522,6 @@ static struct omap_dss_driver taal_driver = {
|
|||
.enable_te = taal_enable_te,
|
||||
.get_te = taal_get_te,
|
||||
|
||||
.set_rotate = taal_rotate,
|
||||
.get_rotate = taal_get_rotate,
|
||||
.set_mirror = taal_mirror,
|
||||
.get_mirror = taal_get_mirror,
|
||||
.run_test = taal_run_test,
|
||||
.memory_read = taal_memory_read,
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
static const struct omap_video_timings tfp410_default_timings = {
|
||||
.x_res = 640,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/slab.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
#define TPO_R02_MODE(x) ((x) & 7)
|
||||
#define TPO_R02_MODE_800x480 7
|
||||
|
@ -278,9 +279,14 @@ static const struct omap_video_timings tpo_td043_timings = {
|
|||
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
|
||||
};
|
||||
|
||||
static inline struct panel_tpo_td043_data
|
||||
*get_panel_data(const struct omap_dss_device *dssdev)
|
||||
{
|
||||
return (struct panel_tpo_td043_data *) dssdev->data;
|
||||
}
|
||||
|
||||
static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
|
||||
{
|
||||
int nreset_gpio = tpo_td043->nreset_gpio;
|
||||
int r;
|
||||
|
||||
if (tpo_td043->powered_on)
|
||||
|
@ -293,8 +299,8 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
|
|||
/* wait for panel to stabilize */
|
||||
msleep(160);
|
||||
|
||||
if (gpio_is_valid(nreset_gpio))
|
||||
gpio_set_value(nreset_gpio, 1);
|
||||
if (gpio_is_valid(tpo_td043->nreset_gpio))
|
||||
gpio_set_value(tpo_td043->nreset_gpio, 1);
|
||||
|
||||
tpo_td043_write(tpo_td043->spi, 2,
|
||||
TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
|
||||
|
@ -311,16 +317,14 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
|
|||
|
||||
static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
|
||||
{
|
||||
int nreset_gpio = tpo_td043->nreset_gpio;
|
||||
|
||||
if (!tpo_td043->powered_on)
|
||||
return;
|
||||
|
||||
tpo_td043_write(tpo_td043->spi, 3,
|
||||
TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
|
||||
|
||||
if (gpio_is_valid(nreset_gpio))
|
||||
gpio_set_value(nreset_gpio, 0);
|
||||
if (gpio_is_valid(tpo_td043->nreset_gpio))
|
||||
gpio_set_value(tpo_td043->nreset_gpio, 0);
|
||||
|
||||
/* wait for at least 2 vsyncs before cutting off power */
|
||||
msleep(50);
|
||||
|
@ -347,12 +351,6 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err0;
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are resuming from system suspend, SPI clocks might not be
|
||||
* enabled yet, so we'll program the LCD from SPI PM resume callback.
|
||||
|
@ -379,9 +377,6 @@ static void tpo_td043_disable_dss(struct omap_dss_device *dssdev)
|
|||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return;
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
|
||||
if (!tpo_td043->spi_suspended)
|
||||
|
@ -407,7 +402,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
|
|||
static int tpo_td043_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = g_tpo_td043;
|
||||
int nreset_gpio = dssdev->reset_gpio;
|
||||
struct panel_tpo_td043_data *pdata = get_panel_data(dssdev);
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(&dssdev->dev, "probe\n");
|
||||
|
@ -417,6 +412,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
tpo_td043->nreset_gpio = pdata->nreset_gpio;
|
||||
|
||||
dssdev->panel.timings = tpo_td043_timings;
|
||||
dssdev->ctrl.pixel_size = 24;
|
||||
|
||||
|
@ -430,9 +430,10 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
|
|||
goto fail_regulator;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(nreset_gpio)) {
|
||||
ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW,
|
||||
"lcd reset");
|
||||
if (gpio_is_valid(tpo_td043->nreset_gpio)) {
|
||||
ret = devm_gpio_request_one(&dssdev->dev,
|
||||
tpo_td043->nreset_gpio, GPIOF_OUT_INIT_LOW,
|
||||
"lcd reset");
|
||||
if (ret < 0) {
|
||||
dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
|
||||
goto fail_gpio_req;
|
||||
|
@ -457,14 +458,11 @@ fail_regulator:
|
|||
static void tpo_td043_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
|
||||
int nreset_gpio = dssdev->reset_gpio;
|
||||
|
||||
dev_dbg(&dssdev->dev, "remove\n");
|
||||
|
||||
sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
|
||||
regulator_put(tpo_td043->vcc_reg);
|
||||
if (gpio_is_valid(nreset_gpio))
|
||||
gpio_free(nreset_gpio);
|
||||
}
|
||||
|
||||
static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
|
||||
|
@ -527,7 +525,6 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
|
|||
return -ENOMEM;
|
||||
|
||||
tpo_td043->spi = spi;
|
||||
tpo_td043->nreset_gpio = dssdev->reset_gpio;
|
||||
dev_set_drvdata(&spi->dev, tpo_td043);
|
||||
g_tpo_td043 = tpo_td043;
|
||||
|
||||
|
|
|
@ -435,20 +435,27 @@ static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_man
|
|||
static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
unsigned long timeout = msecs_to_jiffies(500);
|
||||
struct omap_dss_device *dssdev = mgr->get_device(mgr);
|
||||
u32 irq;
|
||||
int r;
|
||||
|
||||
if (mgr->output == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
|
||||
switch (mgr->output->id) {
|
||||
case OMAP_DSS_OUTPUT_VENC:
|
||||
irq = DISPC_IRQ_EVSYNC_ODD;
|
||||
else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
|
||||
break;
|
||||
case OMAP_DSS_OUTPUT_HDMI:
|
||||
irq = DISPC_IRQ_EVSYNC_EVEN;
|
||||
else
|
||||
break;
|
||||
default:
|
||||
irq = dispc_mgr_get_vsync_irq(mgr->id);
|
||||
break;
|
||||
}
|
||||
|
||||
r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
|
||||
|
||||
|
|
|
@ -181,10 +181,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
|
|||
d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
|
||||
write, &dss_debug_fops);
|
||||
|
||||
if (IS_ERR(d))
|
||||
return PTR_ERR(d);
|
||||
|
||||
return 0;
|
||||
return PTR_RET(d);
|
||||
}
|
||||
#else /* CONFIG_OMAP2_DSS_DEBUGFS */
|
||||
static inline int dss_initialize_debugfs(void)
|
||||
|
|
|
@ -69,6 +69,8 @@ struct dispc_features {
|
|||
u8 mgr_height_start;
|
||||
u16 mgr_width_max;
|
||||
u16 mgr_height_max;
|
||||
unsigned long max_lcd_pclk;
|
||||
unsigned long max_tv_pclk;
|
||||
int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
|
||||
const struct omap_video_timings *mgr_timings,
|
||||
u16 width, u16 height, u16 out_width, u16 out_height,
|
||||
|
@ -85,6 +87,9 @@ struct dispc_features {
|
|||
|
||||
/* no DISPC_IRQ_FRAMEDONETV on this SoC */
|
||||
bool no_framedone_tv:1;
|
||||
|
||||
/* revert to the OMAP4 mechanism of DISPC Smart Standby operation */
|
||||
bool mstandby_workaround:1;
|
||||
};
|
||||
|
||||
#define DISPC_MAX_NR_FIFOS 5
|
||||
|
@ -97,6 +102,8 @@ static struct {
|
|||
|
||||
int irq;
|
||||
|
||||
unsigned long core_clk_rate;
|
||||
|
||||
u32 fifo_size[DISPC_MAX_NR_FIFOS];
|
||||
/* maps which plane is using a fifo. fifo-id -> plane-id */
|
||||
int fifo_assignment[DISPC_MAX_NR_FIFOS];
|
||||
|
@ -1584,6 +1591,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane,
|
|||
}
|
||||
|
||||
static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
|
||||
enum omap_dss_rotation_type rotation_type,
|
||||
bool mirroring, enum omap_color_mode color_mode)
|
||||
{
|
||||
bool row_repeat = false;
|
||||
|
@ -1634,6 +1642,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
|
|||
if (dss_has_feature(FEAT_ROWREPEATENABLE))
|
||||
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
|
||||
row_repeat ? 1 : 0, 18, 18);
|
||||
|
||||
if (color_mode == OMAP_DSS_COLOR_NV12) {
|
||||
bool doublestride = (rotation_type == OMAP_DSS_ROT_TILER) &&
|
||||
(rotation == OMAP_DSS_ROT_0 ||
|
||||
rotation == OMAP_DSS_ROT_180);
|
||||
/* DOUBLESTRIDE */
|
||||
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), doublestride, 22, 22);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int color_mode_to_bpp(enum omap_color_mode color_mode)
|
||||
|
@ -2512,7 +2529,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
|
|||
dispc_ovl_set_vid_color_conv(plane, cconv);
|
||||
}
|
||||
|
||||
dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode);
|
||||
dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, mirror,
|
||||
color_mode);
|
||||
|
||||
dispc_ovl_set_zorder(plane, caps, zorder);
|
||||
dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
|
||||
|
@ -2823,6 +2841,15 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool _dispc_mgr_pclk_ok(enum omap_channel channel,
|
||||
unsigned long pclk)
|
||||
{
|
||||
if (dss_mgr_is_lcd(channel))
|
||||
return pclk <= dispc.feat->max_lcd_pclk ? true : false;
|
||||
else
|
||||
return pclk <= dispc.feat->max_tv_pclk ? true : false;
|
||||
}
|
||||
|
||||
bool dispc_mgr_timings_ok(enum omap_channel channel,
|
||||
const struct omap_video_timings *timings)
|
||||
{
|
||||
|
@ -2830,11 +2857,13 @@ bool dispc_mgr_timings_ok(enum omap_channel channel,
|
|||
|
||||
timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
|
||||
|
||||
if (dss_mgr_is_lcd(channel))
|
||||
timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw,
|
||||
timings->hfp, timings->hbp,
|
||||
timings->vsw, timings->vfp,
|
||||
timings->vbp);
|
||||
timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixel_clock * 1000);
|
||||
|
||||
if (dss_mgr_is_lcd(channel)) {
|
||||
timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
|
||||
timings->hbp, timings->vsw, timings->vfp,
|
||||
timings->vbp);
|
||||
}
|
||||
|
||||
return timings_ok;
|
||||
}
|
||||
|
@ -2951,6 +2980,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
|
|||
|
||||
dispc_write_reg(DISPC_DIVISORo(channel),
|
||||
FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
|
||||
|
||||
if (dss_has_feature(FEAT_CORE_CLK_DIV) == false &&
|
||||
channel == OMAP_DSS_CHANNEL_LCD)
|
||||
dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
|
||||
}
|
||||
|
||||
static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
|
||||
|
@ -3056,15 +3089,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
|
|||
|
||||
unsigned long dispc_core_clk_rate(void)
|
||||
{
|
||||
int lcd;
|
||||
unsigned long fclk = dispc_fclk_rate();
|
||||
|
||||
if (dss_has_feature(FEAT_CORE_CLK_DIV))
|
||||
lcd = REG_GET(DISPC_DIVISOR, 23, 16);
|
||||
else
|
||||
lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
|
||||
|
||||
return fclk / lcd;
|
||||
return dispc.core_clk_rate;
|
||||
}
|
||||
|
||||
static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
|
||||
|
@ -3313,54 +3338,6 @@ static void dispc_dump_regs(struct seq_file *s)
|
|||
#undef DUMPREG
|
||||
}
|
||||
|
||||
/* with fck as input clock rate, find dispc dividers that produce req_pck */
|
||||
void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
|
||||
struct dispc_clock_info *cinfo)
|
||||
{
|
||||
u16 pcd_min, pcd_max;
|
||||
unsigned long best_pck;
|
||||
u16 best_ld, cur_ld;
|
||||
u16 best_pd, cur_pd;
|
||||
|
||||
pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
|
||||
pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
|
||||
|
||||
best_pck = 0;
|
||||
best_ld = 0;
|
||||
best_pd = 0;
|
||||
|
||||
for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
|
||||
unsigned long lck = fck / cur_ld;
|
||||
|
||||
for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) {
|
||||
unsigned long pck = lck / cur_pd;
|
||||
long old_delta = abs(best_pck - req_pck);
|
||||
long new_delta = abs(pck - req_pck);
|
||||
|
||||
if (best_pck == 0 || new_delta < old_delta) {
|
||||
best_pck = pck;
|
||||
best_ld = cur_ld;
|
||||
best_pd = cur_pd;
|
||||
|
||||
if (pck == req_pck)
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (pck < req_pck)
|
||||
break;
|
||||
}
|
||||
|
||||
if (lck / pcd_min < req_pck)
|
||||
break;
|
||||
}
|
||||
|
||||
found:
|
||||
cinfo->lck_div = best_ld;
|
||||
cinfo->pck_div = best_pd;
|
||||
cinfo->lck = fck / cinfo->lck_div;
|
||||
cinfo->pck = cinfo->lck / cinfo->pck_div;
|
||||
}
|
||||
|
||||
/* calculate clock rates using dividers in cinfo */
|
||||
int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
|
||||
struct dispc_clock_info *cinfo)
|
||||
|
@ -3376,6 +3353,66 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool dispc_div_calc(unsigned long dispc,
|
||||
unsigned long pck_min, unsigned long pck_max,
|
||||
dispc_div_calc_func func, void *data)
|
||||
{
|
||||
int lckd, lckd_start, lckd_stop;
|
||||
int pckd, pckd_start, pckd_stop;
|
||||
unsigned long pck, lck;
|
||||
unsigned long lck_max;
|
||||
unsigned long pckd_hw_min, pckd_hw_max;
|
||||
unsigned min_fck_per_pck;
|
||||
unsigned long fck;
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
|
||||
min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
|
||||
#else
|
||||
min_fck_per_pck = 0;
|
||||
#endif
|
||||
|
||||
pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
|
||||
pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
|
||||
|
||||
lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
||||
|
||||
pck_min = pck_min ? pck_min : 1;
|
||||
pck_max = pck_max ? pck_max : ULONG_MAX;
|
||||
|
||||
lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
|
||||
lckd_stop = min(dispc / pck_min, 255ul);
|
||||
|
||||
for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
|
||||
lck = dispc / lckd;
|
||||
|
||||
pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
|
||||
pckd_stop = min(lck / pck_min, pckd_hw_max);
|
||||
|
||||
for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
|
||||
pck = lck / pckd;
|
||||
|
||||
/*
|
||||
* For OMAP2/3 the DISPC fclk is the same as LCD's logic
|
||||
* clock, which means we're configuring DISPC fclk here
|
||||
* also. Thus we need to use the calculated lck. For
|
||||
* OMAP4+ the DISPC fclk is a separate clock.
|
||||
*/
|
||||
if (dss_has_feature(FEAT_CORE_CLK_DIV))
|
||||
fck = dispc_core_clk_rate();
|
||||
else
|
||||
fck = lck;
|
||||
|
||||
if (fck < pck * min_fck_per_pck)
|
||||
continue;
|
||||
|
||||
if (func(lckd, pckd, lck, pck, data))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void dispc_mgr_set_clock_div(enum omap_channel channel,
|
||||
const struct dispc_clock_info *cinfo)
|
||||
{
|
||||
|
@ -3451,6 +3488,8 @@ static void _omap_dispc_initial_config(void)
|
|||
l = FLD_MOD(l, 1, 0, 0);
|
||||
l = FLD_MOD(l, 1, 23, 16);
|
||||
dispc_write_reg(DISPC_DIVISOR, l);
|
||||
|
||||
dispc.core_clk_rate = dispc_fclk_rate();
|
||||
}
|
||||
|
||||
/* FUNCGATED */
|
||||
|
@ -3466,6 +3505,9 @@ static void _omap_dispc_initial_config(void)
|
|||
dispc_configure_burst_sizes();
|
||||
|
||||
dispc_ovl_enable_zorder_planes();
|
||||
|
||||
if (dispc.feat->mstandby_workaround)
|
||||
REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0);
|
||||
}
|
||||
|
||||
static const struct dispc_features omap24xx_dispc_feats __initconst = {
|
||||
|
@ -3479,6 +3521,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
|
|||
.mgr_height_start = 26,
|
||||
.mgr_width_max = 2048,
|
||||
.mgr_height_max = 2048,
|
||||
.max_lcd_pclk = 66500000,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_24xx,
|
||||
.calc_core_clk = calc_core_clk_24xx,
|
||||
.num_fifos = 3,
|
||||
|
@ -3496,6 +3539,8 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
|
|||
.mgr_height_start = 26,
|
||||
.mgr_width_max = 2048,
|
||||
.mgr_height_max = 2048,
|
||||
.max_lcd_pclk = 173000000,
|
||||
.max_tv_pclk = 59000000,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_34xx,
|
||||
.calc_core_clk = calc_core_clk_34xx,
|
||||
.num_fifos = 3,
|
||||
|
@ -3513,6 +3558,8 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
|
|||
.mgr_height_start = 26,
|
||||
.mgr_width_max = 2048,
|
||||
.mgr_height_max = 2048,
|
||||
.max_lcd_pclk = 173000000,
|
||||
.max_tv_pclk = 59000000,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_34xx,
|
||||
.calc_core_clk = calc_core_clk_34xx,
|
||||
.num_fifos = 3,
|
||||
|
@ -3530,6 +3577,8 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
|
|||
.mgr_height_start = 26,
|
||||
.mgr_width_max = 2048,
|
||||
.mgr_height_max = 2048,
|
||||
.max_lcd_pclk = 170000000,
|
||||
.max_tv_pclk = 185625000,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_44xx,
|
||||
.calc_core_clk = calc_core_clk_44xx,
|
||||
.num_fifos = 5,
|
||||
|
@ -3547,10 +3596,13 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = {
|
|||
.mgr_height_start = 27,
|
||||
.mgr_width_max = 4096,
|
||||
.mgr_height_max = 4096,
|
||||
.max_lcd_pclk = 170000000,
|
||||
.max_tv_pclk = 186000000,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_44xx,
|
||||
.calc_core_clk = calc_core_clk_44xx,
|
||||
.num_fifos = 5,
|
||||
.gfx_fifo_workaround = true,
|
||||
.mstandby_workaround = true,
|
||||
};
|
||||
|
||||
static int __init dispc_init_features(struct platform_device *pdev)
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define DISPC_GLOBAL_BUFFER 0x0800
|
||||
#define DISPC_CONTROL3 0x0848
|
||||
#define DISPC_CONFIG3 0x084C
|
||||
#define DISPC_MSTANDBY_CTRL 0x0858
|
||||
|
||||
/* DISPC overlay registers */
|
||||
#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
|
||||
|
|
|
@ -63,15 +63,29 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
|
|||
case OMAPDSS_VER_OMAP3630:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
return NULL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return dsi_get_dsidev_from_id(0);
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return dsi_get_dsidev_from_id(1);
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return dsi_get_dsidev_from_id(0);
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return dsi_get_dsidev_from_id(1);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return dsi_get_dsidev_from_id(0);
|
||||
case OMAP_DSS_CHANNEL_LCD3:
|
||||
return dsi_get_dsidev_from_id(1);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -91,75 +105,211 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
|
|||
}
|
||||
}
|
||||
|
||||
static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
|
||||
unsigned long pck_req, unsigned long *fck, int *lck_div,
|
||||
int *pck_div)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
struct dpi_clk_calc_ctx {
|
||||
struct platform_device *dsidev;
|
||||
|
||||
/* inputs */
|
||||
|
||||
unsigned long pck_min, pck_max;
|
||||
|
||||
/* outputs */
|
||||
|
||||
struct dsi_clock_info dsi_cinfo;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
int r;
|
||||
|
||||
r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo,
|
||||
&dispc_cinfo);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dss_select_lcd_clk_source(mgr->id,
|
||||
dpi_get_alt_clk_src(mgr->id));
|
||||
|
||||
dpi.mgr_config.clock_info = dispc_cinfo;
|
||||
|
||||
*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
|
||||
*lck_div = dispc_cinfo.lck_div;
|
||||
*pck_div = dispc_cinfo.pck_div;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
|
||||
unsigned long pck_req, unsigned long *fck, int *lck_div,
|
||||
int *pck_div)
|
||||
{
|
||||
struct dss_clock_info dss_cinfo;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
};
|
||||
|
||||
static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
|
||||
unsigned long pck, void *data)
|
||||
{
|
||||
struct dpi_clk_calc_ctx *ctx = data;
|
||||
|
||||
/*
|
||||
* Odd dividers give us uneven duty cycle, causing problem when level
|
||||
* shifted. So skip all odd dividers when the pixel clock is on the
|
||||
* higher side.
|
||||
*/
|
||||
if (ctx->pck_min >= 1000000) {
|
||||
if (lckd > 1 && lckd % 2 != 0)
|
||||
return false;
|
||||
|
||||
if (pckd > 1 && pckd % 2 != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->dispc_cinfo.lck_div = lckd;
|
||||
ctx->dispc_cinfo.pck_div = pckd;
|
||||
ctx->dispc_cinfo.lck = lck;
|
||||
ctx->dispc_cinfo.pck = pck;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
|
||||
void *data)
|
||||
{
|
||||
struct dpi_clk_calc_ctx *ctx = data;
|
||||
|
||||
/*
|
||||
* Odd dividers give us uneven duty cycle, causing problem when level
|
||||
* shifted. So skip all odd dividers when the pixel clock is on the
|
||||
* higher side.
|
||||
*/
|
||||
if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 1000000)
|
||||
return false;
|
||||
|
||||
ctx->dsi_cinfo.regm_dispc = regm_dispc;
|
||||
ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
|
||||
|
||||
return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
|
||||
dpi_calc_dispc_cb, ctx);
|
||||
}
|
||||
|
||||
|
||||
static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
|
||||
unsigned long pll,
|
||||
void *data)
|
||||
{
|
||||
struct dpi_clk_calc_ctx *ctx = data;
|
||||
|
||||
ctx->dsi_cinfo.regn = regn;
|
||||
ctx->dsi_cinfo.regm = regm;
|
||||
ctx->dsi_cinfo.fint = fint;
|
||||
ctx->dsi_cinfo.clkin4ddr = pll;
|
||||
|
||||
return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
|
||||
dpi_calc_hsdiv_cb, ctx);
|
||||
}
|
||||
|
||||
static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
|
||||
{
|
||||
struct dpi_clk_calc_ctx *ctx = data;
|
||||
|
||||
ctx->dss_cinfo.fck = fck;
|
||||
ctx->dss_cinfo.fck_div = fckd;
|
||||
|
||||
return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
|
||||
dpi_calc_dispc_cb, ctx);
|
||||
}
|
||||
|
||||
static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
|
||||
{
|
||||
unsigned long clkin;
|
||||
unsigned long pll_min, pll_max;
|
||||
|
||||
clkin = dsi_get_pll_clkin(dpi.dsidev);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->dsidev = dpi.dsidev;
|
||||
ctx->pck_min = pck - 1000;
|
||||
ctx->pck_max = pck + 1000;
|
||||
ctx->dsi_cinfo.clkin = clkin;
|
||||
|
||||
pll_min = 0;
|
||||
pll_max = 0;
|
||||
|
||||
return dsi_pll_calc(dpi.dsidev, clkin,
|
||||
pll_min, pll_max,
|
||||
dpi_calc_pll_cb, ctx);
|
||||
}
|
||||
|
||||
static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* DSS fck gives us very few possibilities, so finding a good pixel
|
||||
* clock may not be possible. We try multiple times to find the clock,
|
||||
* each time widening the pixel clock range we look for, up to
|
||||
* +/- ~15MHz.
|
||||
*/
|
||||
|
||||
for (i = 0; i < 25; ++i) {
|
||||
bool ok;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
if (pck > 1000 * i * i * i)
|
||||
ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
|
||||
else
|
||||
ctx->pck_min = 0;
|
||||
ctx->pck_max = pck + 1000 * i * i * i;
|
||||
|
||||
ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx);
|
||||
if (ok)
|
||||
return ok;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dpi_set_dsi_clk(enum omap_channel channel,
|
||||
unsigned long pck_req, unsigned long *fck, int *lck_div,
|
||||
int *pck_div)
|
||||
{
|
||||
struct dpi_clk_calc_ctx ctx;
|
||||
int r;
|
||||
bool ok;
|
||||
|
||||
r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo);
|
||||
ok = dpi_dsi_clk_calc(pck_req, &ctx);
|
||||
if (!ok)
|
||||
return -EINVAL;
|
||||
|
||||
r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dss_set_clock_div(&dss_cinfo);
|
||||
if (r)
|
||||
return r;
|
||||
dss_select_lcd_clk_source(channel,
|
||||
dpi_get_alt_clk_src(channel));
|
||||
|
||||
dpi.mgr_config.clock_info = dispc_cinfo;
|
||||
dpi.mgr_config.clock_info = ctx.dispc_cinfo;
|
||||
|
||||
*fck = dss_cinfo.fck;
|
||||
*lck_div = dispc_cinfo.lck_div;
|
||||
*pck_div = dispc_cinfo.pck_div;
|
||||
*fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
|
||||
*lck_div = ctx.dispc_cinfo.lck_div;
|
||||
*pck_div = ctx.dispc_cinfo.pck_div;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dpi_set_mode(struct omap_dss_device *dssdev)
|
||||
static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
|
||||
int *lck_div, int *pck_div)
|
||||
{
|
||||
struct dpi_clk_calc_ctx ctx;
|
||||
int r;
|
||||
bool ok;
|
||||
|
||||
ok = dpi_dss_clk_calc(pck_req, &ctx);
|
||||
if (!ok)
|
||||
return -EINVAL;
|
||||
|
||||
r = dss_set_clock_div(&ctx.dss_cinfo);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dpi.mgr_config.clock_info = ctx.dispc_cinfo;
|
||||
|
||||
*fck = ctx.dss_cinfo.fck;
|
||||
*lck_div = ctx.dispc_cinfo.lck_div;
|
||||
*pck_div = ctx.dispc_cinfo.pck_div;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dpi_set_mode(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
struct omap_video_timings *t = &dpi.timings;
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
int lck_div = 0, pck_div = 0;
|
||||
unsigned long fck = 0;
|
||||
unsigned long pck;
|
||||
int r = 0;
|
||||
|
||||
if (dpi.dsidev)
|
||||
r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
|
||||
r = dpi_set_dsi_clk(mgr->id, t->pixel_clock * 1000, &fck,
|
||||
&lck_div, &pck_div);
|
||||
else
|
||||
r = dpi_set_dispc_clk(dssdev, t->pixel_clock * 1000, &fck,
|
||||
r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck,
|
||||
&lck_div, &pck_div);
|
||||
if (r)
|
||||
return r;
|
||||
|
@ -179,10 +329,8 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
|
||||
static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
|
||||
|
||||
dpi.mgr_config.stallmode = false;
|
||||
|
@ -197,7 +345,7 @@ static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
|
|||
|
||||
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
struct omap_dss_output *out = &dpi.output;
|
||||
int r;
|
||||
|
||||
mutex_lock(&dpi.lock);
|
||||
|
@ -230,7 +378,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err_get_dispc;
|
||||
|
||||
r = dss_dpi_select_source(dssdev->channel);
|
||||
r = dss_dpi_select_source(out->manager->id);
|
||||
if (r)
|
||||
goto err_src_sel;
|
||||
|
||||
|
@ -244,11 +392,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err_dsi_pll_init;
|
||||
}
|
||||
|
||||
r = dpi_set_mode(dssdev);
|
||||
r = dpi_set_mode(out->manager);
|
||||
if (r)
|
||||
goto err_set_mode;
|
||||
|
||||
dpi_config_lcd_manager(dssdev);
|
||||
dpi_config_lcd_manager(out->manager);
|
||||
|
||||
mdelay(2);
|
||||
|
||||
|
@ -285,7 +433,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable);
|
|||
|
||||
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
struct omap_overlay_manager *mgr = dpi.output.manager;
|
||||
|
||||
mutex_lock(&dpi.lock);
|
||||
|
||||
|
@ -324,12 +472,12 @@ EXPORT_SYMBOL(omapdss_dpi_set_timings);
|
|||
int dpi_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
int r;
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
struct omap_overlay_manager *mgr = dpi.output.manager;
|
||||
int lck_div, pck_div;
|
||||
unsigned long fck;
|
||||
unsigned long pck;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
struct dpi_clk_calc_ctx ctx;
|
||||
bool ok;
|
||||
|
||||
if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
|
||||
return -EINVAL;
|
||||
|
@ -338,28 +486,21 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
|
|||
return -EINVAL;
|
||||
|
||||
if (dpi.dsidev) {
|
||||
struct dsi_clock_info dsi_cinfo;
|
||||
r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
|
||||
timings->pixel_clock * 1000,
|
||||
&dsi_cinfo, &dispc_cinfo);
|
||||
ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx);
|
||||
if (!ok)
|
||||
return -EINVAL;
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
|
||||
fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
|
||||
} else {
|
||||
struct dss_clock_info dss_cinfo;
|
||||
r = dss_calc_clock_div(timings->pixel_clock * 1000,
|
||||
&dss_cinfo, &dispc_cinfo);
|
||||
ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &ctx);
|
||||
if (!ok)
|
||||
return -EINVAL;
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
fck = dss_cinfo.fck;
|
||||
fck = ctx.dss_cinfo.fck;
|
||||
}
|
||||
|
||||
lck_div = dispc_cinfo.lck_div;
|
||||
pck_div = dispc_cinfo.pck_div;
|
||||
lck_div = ctx.dispc_cinfo.lck_div;
|
||||
pck_div = ctx.dispc_cinfo.pck_div;
|
||||
|
||||
pck = fck / lck_div / pck_div / 1000;
|
||||
|
||||
|
@ -401,6 +542,36 @@ static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a hardcoded channel for the DPI output. This should work for
|
||||
* current use cases, but this can be later expanded to either resolve
|
||||
* the channel in some more dynamic manner, or get the channel as a user
|
||||
* parameter.
|
||||
*/
|
||||
static enum omap_channel dpi_get_channel(void)
|
||||
{
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
return OMAP_DSS_CHANNEL_LCD;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
return OMAP_DSS_CHANNEL_LCD2;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
return OMAP_DSS_CHANNEL_LCD3;
|
||||
|
||||
default:
|
||||
DSSWARN("unsupported DSS version\n");
|
||||
return OMAP_DSS_CHANNEL_LCD;
|
||||
}
|
||||
}
|
||||
|
||||
static int __init dpi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev;
|
||||
|
@ -421,12 +592,7 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
|
|||
dpi.vdds_dsi_reg = vdds_dsi;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX We shouldn't need dssdev->channel for this. The dsi pll clock
|
||||
* source for DPI is SoC integration detail, not something that should
|
||||
* be configured in the dssdev
|
||||
*/
|
||||
dsidev = dpi_get_dsidev(dssdev->channel);
|
||||
dsidev = dpi_get_dsidev(dpi.output.dispc_channel);
|
||||
|
||||
if (dsidev && dpi_verify_dsi_pll(dsidev)) {
|
||||
dsidev = NULL;
|
||||
|
@ -517,6 +683,8 @@ static void __init dpi_init_output(struct platform_device *pdev)
|
|||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_DPI;
|
||||
out->type = OMAP_DISPLAY_TYPE_DPI;
|
||||
out->name = "dpi.0";
|
||||
out->dispc_channel = dpi_get_channel();
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -473,6 +473,47 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
|
||||
{
|
||||
int fckd, fckd_start, fckd_stop;
|
||||
unsigned long fck;
|
||||
unsigned long fck_hw_max;
|
||||
unsigned long fckd_hw_max;
|
||||
unsigned long prate;
|
||||
unsigned m;
|
||||
|
||||
if (dss.dpll4_m4_ck == NULL) {
|
||||
/*
|
||||
* TODO: dss1_fclk can be changed on OMAP2, but the available
|
||||
* dividers are not continuous. We just use the pre-set rate for
|
||||
* now.
|
||||
*/
|
||||
fck = clk_get_rate(dss.dss_clk);
|
||||
fckd = 1;
|
||||
return func(fckd, fck, data);
|
||||
}
|
||||
|
||||
fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
||||
fckd_hw_max = dss.feat->fck_div_max;
|
||||
|
||||
m = dss.feat->dss_fck_multiplier;
|
||||
prate = dss_get_dpll4_rate();
|
||||
|
||||
fck_min = fck_min ? fck_min : 1;
|
||||
|
||||
fckd_start = min(prate * m / fck_min, fckd_hw_max);
|
||||
fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
|
||||
|
||||
for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
|
||||
fck = prate / fckd * m;
|
||||
|
||||
if (func(fckd, fck, data))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int dss_set_clock_div(struct dss_clock_info *cinfo)
|
||||
{
|
||||
if (dss.dpll4_m4_ck) {
|
||||
|
@ -482,7 +523,8 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
|
|||
prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
DSSDBG("dpll4_m4 = %ld\n", prate);
|
||||
|
||||
r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
|
||||
r = clk_set_rate(dss.dpll4_m4_ck,
|
||||
DIV_ROUND_UP(prate, cinfo->fck_div));
|
||||
if (r)
|
||||
return r;
|
||||
} else {
|
||||
|
@ -492,7 +534,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
|
|||
|
||||
dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
|
||||
|
||||
WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch");
|
||||
WARN_ONCE(dss.dss_clk_rate != cinfo->fck,
|
||||
"clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
|
||||
cinfo->fck);
|
||||
|
||||
DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
|
||||
|
||||
|
@ -542,121 +586,6 @@ static int dss_setup_default_clock(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo)
|
||||
{
|
||||
unsigned long prate;
|
||||
struct dss_clock_info best_dss;
|
||||
struct dispc_clock_info best_dispc;
|
||||
|
||||
unsigned long fck, max_dss_fck;
|
||||
|
||||
u16 fck_div;
|
||||
|
||||
int match = 0;
|
||||
int min_fck_per_pck;
|
||||
|
||||
prate = dss_get_dpll4_rate();
|
||||
|
||||
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
||||
|
||||
fck = clk_get_rate(dss.dss_clk);
|
||||
if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
|
||||
dss.cache_dss_cinfo.fck == fck) {
|
||||
DSSDBG("dispc clock info found from cache.\n");
|
||||
*dss_cinfo = dss.cache_dss_cinfo;
|
||||
*dispc_cinfo = dss.cache_dispc_cinfo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
|
||||
|
||||
if (min_fck_per_pck &&
|
||||
req_pck * min_fck_per_pck > max_dss_fck) {
|
||||
DSSERR("Requested pixel clock not possible with the current "
|
||||
"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
|
||||
"the constraint off.\n");
|
||||
min_fck_per_pck = 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
memset(&best_dss, 0, sizeof(best_dss));
|
||||
memset(&best_dispc, 0, sizeof(best_dispc));
|
||||
|
||||
if (dss.dpll4_m4_ck == NULL) {
|
||||
struct dispc_clock_info cur_dispc;
|
||||
/* XXX can we change the clock on omap2? */
|
||||
fck = clk_get_rate(dss.dss_clk);
|
||||
fck_div = 1;
|
||||
|
||||
dispc_find_clk_divs(req_pck, fck, &cur_dispc);
|
||||
match = 1;
|
||||
|
||||
best_dss.fck = fck;
|
||||
best_dss.fck_div = fck_div;
|
||||
|
||||
best_dispc = cur_dispc;
|
||||
|
||||
goto found;
|
||||
} else {
|
||||
for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
|
||||
struct dispc_clock_info cur_dispc;
|
||||
|
||||
fck = prate / fck_div * dss.feat->dss_fck_multiplier;
|
||||
|
||||
if (fck > max_dss_fck)
|
||||
continue;
|
||||
|
||||
if (min_fck_per_pck &&
|
||||
fck < req_pck * min_fck_per_pck)
|
||||
continue;
|
||||
|
||||
match = 1;
|
||||
|
||||
dispc_find_clk_divs(req_pck, fck, &cur_dispc);
|
||||
|
||||
if (abs(cur_dispc.pck - req_pck) <
|
||||
abs(best_dispc.pck - req_pck)) {
|
||||
|
||||
best_dss.fck = fck;
|
||||
best_dss.fck_div = fck_div;
|
||||
|
||||
best_dispc = cur_dispc;
|
||||
|
||||
if (cur_dispc.pck == req_pck)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
if (!match) {
|
||||
if (min_fck_per_pck) {
|
||||
DSSERR("Could not find suitable clock settings.\n"
|
||||
"Turning FCK/PCK constraint off and"
|
||||
"trying again.\n");
|
||||
min_fck_per_pck = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
DSSERR("Could not find suitable clock settings.\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dss_cinfo)
|
||||
*dss_cinfo = best_dss;
|
||||
if (dispc_cinfo)
|
||||
*dispc_cinfo = best_dispc;
|
||||
|
||||
dss.cache_req_pck = req_pck;
|
||||
dss.cache_prate = prate;
|
||||
dss.cache_dss_cinfo = best_dss;
|
||||
dss.cache_dispc_cinfo = best_dispc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dss_set_venc_output(enum omap_dss_venc_type type)
|
||||
{
|
||||
int l = 0;
|
||||
|
@ -767,13 +696,11 @@ int dss_dpi_select_source(enum omap_channel channel)
|
|||
static int dss_get_clocks(void)
|
||||
{
|
||||
struct clk *clk;
|
||||
int r;
|
||||
|
||||
clk = clk_get(&dss.pdev->dev, "fck");
|
||||
clk = devm_clk_get(&dss.pdev->dev, "fck");
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("can't get clock fck\n");
|
||||
r = PTR_ERR(clk);
|
||||
goto err;
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
dss.dss_clk = clk;
|
||||
|
@ -782,8 +709,7 @@ static int dss_get_clocks(void)
|
|||
clk = clk_get(NULL, dss.feat->clk_name);
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("Failed to get %s\n", dss.feat->clk_name);
|
||||
r = PTR_ERR(clk);
|
||||
goto err;
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
} else {
|
||||
clk = NULL;
|
||||
|
@ -792,21 +718,12 @@ static int dss_get_clocks(void)
|
|||
dss.dpll4_m4_ck = clk;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (dss.dss_clk)
|
||||
clk_put(dss.dss_clk);
|
||||
if (dss.dpll4_m4_ck)
|
||||
clk_put(dss.dpll4_m4_ck);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void dss_put_clocks(void)
|
||||
{
|
||||
if (dss.dpll4_m4_ck)
|
||||
clk_put(dss.dpll4_m4_ck);
|
||||
clk_put(dss.dss_clk);
|
||||
}
|
||||
|
||||
static int dss_runtime_get(void)
|
||||
|
|
|
@ -268,8 +268,9 @@ void dss_set_dac_pwrdn_bgz(bool enable);
|
|||
unsigned long dss_get_dpll4_rate(void);
|
||||
int dss_calc_clock_rates(struct dss_clock_info *cinfo);
|
||||
int dss_set_clock_div(struct dss_clock_info *cinfo);
|
||||
int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo);
|
||||
|
||||
typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
|
||||
bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
|
||||
|
||||
/* SDI */
|
||||
int sdi_init_platform_driver(void) __init;
|
||||
|
@ -292,12 +293,21 @@ void dsi_dump_clocks(struct seq_file *s);
|
|||
void dsi_irq_handler(void);
|
||||
u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
|
||||
|
||||
unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
|
||||
|
||||
typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
|
||||
unsigned long pll, void *data);
|
||||
typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
|
||||
void *data);
|
||||
bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
|
||||
unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
|
||||
bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
|
||||
unsigned long pll_min, unsigned long pll_max,
|
||||
dsi_pll_calc_func func, void *data);
|
||||
|
||||
unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
|
||||
int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
||||
struct dsi_clock_info *cinfo);
|
||||
int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
|
||||
unsigned long req_pck, struct dsi_clock_info *cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo);
|
||||
int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
|
||||
bool enable_hsdiv);
|
||||
void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
|
||||
|
@ -328,14 +338,6 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
|||
WARN("%s: DSI not compiled in\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
|
||||
unsigned long req_pck,
|
||||
struct dsi_clock_info *dsi_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo)
|
||||
{
|
||||
WARN("%s: DSI not compiled in\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int dsi_pll_init(struct platform_device *dsidev,
|
||||
bool enable_hsclk, bool enable_hsdiv)
|
||||
{
|
||||
|
@ -376,11 +378,15 @@ void dispc_enable_fifomerge(bool enable);
|
|||
void dispc_enable_gamma_table(bool enable);
|
||||
void dispc_set_loadmode(enum omap_dss_load_mode mode);
|
||||
|
||||
typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck,
|
||||
unsigned long pck, void *data);
|
||||
bool dispc_div_calc(unsigned long dispc,
|
||||
unsigned long pck_min, unsigned long pck_max,
|
||||
dispc_div_calc_func func, void *data);
|
||||
|
||||
bool dispc_mgr_timings_ok(enum omap_channel channel,
|
||||
const struct omap_video_timings *timings);
|
||||
unsigned long dispc_fclk_rate(void);
|
||||
void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
|
||||
struct dispc_clock_info *cinfo);
|
||||
int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
|
||||
struct dispc_clock_info *cinfo);
|
||||
|
||||
|
|
|
@ -414,7 +414,7 @@ static const char * const omap5_dss_clk_source_names[] = {
|
|||
};
|
||||
|
||||
static const struct dss_param_range omap2_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 133000000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 2, 255 },
|
||||
[FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
|
||||
[FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
|
||||
|
@ -459,15 +459,15 @@ static const struct dss_param_range omap4_dss_param_range[] = {
|
|||
};
|
||||
|
||||
static const struct dss_param_range omap5_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 200000000 },
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 209250000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
|
||||
[FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
|
||||
[FEAT_PARAM_DSIPLL_FINT] = { 150000, 52000000 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 209250000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
|
||||
};
|
||||
|
|
|
@ -472,17 +472,12 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
|
|||
* Input clock is predivided by N + 1
|
||||
* out put of which is reference clk
|
||||
*/
|
||||
if (dssdev->clocks.hdmi.regn == 0)
|
||||
pi->regn = HDMI_DEFAULT_REGN;
|
||||
else
|
||||
pi->regn = dssdev->clocks.hdmi.regn;
|
||||
|
||||
pi->regn = HDMI_DEFAULT_REGN;
|
||||
|
||||
refclk = clkin / pi->regn;
|
||||
|
||||
if (dssdev->clocks.hdmi.regm2 == 0)
|
||||
pi->regm2 = HDMI_DEFAULT_REGM2;
|
||||
else
|
||||
pi->regm2 = dssdev->clocks.hdmi.regm2;
|
||||
pi->regm2 = HDMI_DEFAULT_REGM2;
|
||||
|
||||
/*
|
||||
* multiplier is pixel_clk/ref_clk
|
||||
|
@ -804,7 +799,7 @@ static int hdmi_get_clocks(struct platform_device *pdev)
|
|||
{
|
||||
struct clk *clk;
|
||||
|
||||
clk = clk_get(&pdev->dev, "sys_clk");
|
||||
clk = devm_clk_get(&pdev->dev, "sys_clk");
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("can't get sys_clk\n");
|
||||
return PTR_ERR(clk);
|
||||
|
@ -815,12 +810,6 @@ static int hdmi_get_clocks(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void hdmi_put_clocks(void)
|
||||
{
|
||||
if (hdmi.sys_clk)
|
||||
clk_put(hdmi.sys_clk);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
|
||||
{
|
||||
|
@ -1017,8 +1006,6 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
|
|||
hdmi.ls_oe_gpio = priv->ls_oe_gpio;
|
||||
hdmi.hpd_gpio = priv->hpd_gpio;
|
||||
|
||||
dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
|
||||
r = hdmi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
|
@ -1051,6 +1038,8 @@ static void __init hdmi_init_output(struct platform_device *pdev)
|
|||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_HDMI;
|
||||
out->type = OMAP_DISPLAY_TYPE_HDMI;
|
||||
out->name = "hdmi.0";
|
||||
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
@ -1097,23 +1086,19 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
|||
hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
|
||||
hdmi.ip_data.phy_offset = HDMI_PHY;
|
||||
|
||||
hdmi_init_output(pdev);
|
||||
|
||||
r = hdmi_panel_init();
|
||||
if (r) {
|
||||
DSSERR("can't init panel\n");
|
||||
goto err_panel_init;
|
||||
return r;
|
||||
}
|
||||
|
||||
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
|
||||
|
||||
hdmi_init_output(pdev);
|
||||
|
||||
hdmi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_panel_init:
|
||||
hdmi_put_clocks();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int __exit hdmi_remove_child(struct device *dev, void *data)
|
||||
|
@ -1135,8 +1120,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
|
|||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
hdmi_put_clocks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_dss_get_output);
|
||||
|
||||
static const struct dss_mgr_ops *dss_mgr_ops;
|
||||
|
||||
|
|
|
@ -1025,6 +1025,8 @@ static void __init rfbi_init_output(struct platform_device *pdev)
|
|||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_DBI;
|
||||
out->type = OMAP_DISPLAY_TYPE_DBI;
|
||||
out->name = "rfbi.0";
|
||||
out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,72 @@ static struct {
|
|||
struct omap_dss_output output;
|
||||
} sdi;
|
||||
|
||||
struct sdi_clk_calc_ctx {
|
||||
unsigned long pck_min, pck_max;
|
||||
|
||||
struct dss_clock_info dss_cinfo;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
};
|
||||
|
||||
static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
|
||||
unsigned long pck, void *data)
|
||||
{
|
||||
struct sdi_clk_calc_ctx *ctx = data;
|
||||
|
||||
ctx->dispc_cinfo.lck_div = lckd;
|
||||
ctx->dispc_cinfo.pck_div = pckd;
|
||||
ctx->dispc_cinfo.lck = lck;
|
||||
ctx->dispc_cinfo.pck = pck;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
|
||||
{
|
||||
struct sdi_clk_calc_ctx *ctx = data;
|
||||
|
||||
ctx->dss_cinfo.fck = fck;
|
||||
ctx->dss_cinfo.fck_div = fckd;
|
||||
|
||||
return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
|
||||
dpi_calc_dispc_cb, ctx);
|
||||
}
|
||||
|
||||
static int sdi_calc_clock_div(unsigned long pclk,
|
||||
struct dss_clock_info *dss_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo)
|
||||
{
|
||||
int i;
|
||||
struct sdi_clk_calc_ctx ctx;
|
||||
|
||||
/*
|
||||
* DSS fclk gives us very few possibilities, so finding a good pixel
|
||||
* clock may not be possible. We try multiple times to find the clock,
|
||||
* each time widening the pixel clock range we look for, up to
|
||||
* +/- 1MHz.
|
||||
*/
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
bool ok;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
if (pclk > 1000 * i * i * i)
|
||||
ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
|
||||
else
|
||||
ctx.pck_min = 0;
|
||||
ctx.pck_max = pclk + 1000 * i * i * i;
|
||||
|
||||
ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx);
|
||||
if (ok) {
|
||||
*dss_cinfo = ctx.dss_cinfo;
|
||||
*dispc_cinfo = ctx.dispc_cinfo;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
@ -88,7 +154,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
|||
t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
|
||||
t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
|
||||
|
||||
r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
|
||||
r = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
|
||||
if (r)
|
||||
goto err_calc_clock_div;
|
||||
|
||||
|
@ -278,6 +344,8 @@ static void __init sdi_init_output(struct platform_device *pdev)
|
|||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_SDI;
|
||||
out->type = OMAP_DISPLAY_TYPE_SDI;
|
||||
out->name = "sdi.0";
|
||||
out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
|
|
@ -519,10 +519,6 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err0;
|
||||
}
|
||||
|
||||
if (dssdev->platform_enable)
|
||||
dssdev->platform_enable(dssdev);
|
||||
|
||||
|
||||
r = venc_power_on(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
|
@ -533,8 +529,6 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
|
|||
|
||||
return 0;
|
||||
err1:
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
omap_dss_stop_device(dssdev);
|
||||
err0:
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
|
@ -551,9 +545,6 @@ void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
|
|||
|
||||
omap_dss_stop_device(dssdev);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
}
|
||||
|
||||
|
@ -721,7 +712,7 @@ static int venc_get_clocks(struct platform_device *pdev)
|
|||
struct clk *clk;
|
||||
|
||||
if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
|
||||
clk = clk_get(&pdev->dev, "tv_dac_clk");
|
||||
clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("can't get tv_dac_clk\n");
|
||||
return PTR_ERR(clk);
|
||||
|
@ -735,12 +726,6 @@ static int venc_get_clocks(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void venc_put_clocks(void)
|
||||
{
|
||||
if (venc.tv_dac_clk)
|
||||
clk_put(venc.tv_dac_clk);
|
||||
}
|
||||
|
||||
static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
|
@ -786,8 +771,6 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
|
|||
|
||||
dss_copy_device_pdata(dssdev, plat_dssdev);
|
||||
|
||||
dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
|
||||
r = venc_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
|
@ -819,6 +802,8 @@ static void __init venc_init_output(struct platform_device *pdev)
|
|||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_VENC;
|
||||
out->type = OMAP_DISPLAY_TYPE_VENC;
|
||||
out->name = "venc.0";
|
||||
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
@ -886,7 +871,6 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
|
|||
err_panel_init:
|
||||
err_runtime_get:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
venc_put_clocks();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -904,7 +888,6 @@ static int __exit omap_venchw_remove(struct platform_device *pdev)
|
|||
venc_uninit_output(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
venc_put_clocks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2388,7 +2388,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev,
|
|||
struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
|
||||
mgr = omap_dss_get_overlay_manager(dssdev->channel);
|
||||
mgr = omap_dss_get_overlay_manager(out->dispc_channel);
|
||||
|
||||
if (!mgr || !out)
|
||||
continue;
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Header containing platform_data structs for omap panels
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
* Archit Taneja <archit@ti.com>
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments
|
||||
* Author: Mayuresh Janorkar <mayur@ti.com>
|
||||
*
|
||||
* Copyright (C) 2010 Canonical Ltd.
|
||||
* Author: Bryan Wu <bryan.wu@canonical.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 __OMAP_PANEL_DATA_H
|
||||
#define __OMAP_PANEL_DATA_H
|
||||
|
||||
struct omap_dss_device;
|
||||
|
||||
/**
|
||||
* struct panel_generic_dpi_data - panel driver configuration data
|
||||
* @name: panel name
|
||||
* @platform_enable: platform specific panel enable function
|
||||
* @platform_disable: platform specific panel disable function
|
||||
* @num_gpios: number of gpios connected to panel
|
||||
* @gpios: gpio numbers on the platform
|
||||
* @gpio_invert: configure gpio as active high or low
|
||||
*/
|
||||
struct panel_generic_dpi_data {
|
||||
const char *name;
|
||||
int (*platform_enable)(struct omap_dss_device *dssdev);
|
||||
void (*platform_disable)(struct omap_dss_device *dssdev);
|
||||
|
||||
int num_gpios;
|
||||
int gpios[10];
|
||||
bool gpio_invert[10];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct panel_n8x0_data - N800 panel driver configuration data
|
||||
*/
|
||||
struct panel_n8x0_data {
|
||||
int (*platform_enable)(struct omap_dss_device *dssdev);
|
||||
void (*platform_disable)(struct omap_dss_device *dssdev);
|
||||
int panel_reset;
|
||||
int ctrl_pwrdown;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct nokia_dsi_panel_data - Nokia DSI panel driver configuration data
|
||||
* @name: panel name
|
||||
* @use_ext_te: use external TE
|
||||
* @ext_te_gpio: external TE GPIO
|
||||
* @esd_interval: interval of ESD checks, 0 = disabled (ms)
|
||||
* @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
|
||||
* @use_dsi_backlight: true if panel uses DSI command to control backlight
|
||||
* @pin_config: DSI pin configuration
|
||||
*/
|
||||
|
||||
struct nokia_dsi_panel_data {
|
||||
const char *name;
|
||||
|
||||
int reset_gpio;
|
||||
|
||||
bool use_ext_te;
|
||||
int ext_te_gpio;
|
||||
|
||||
unsigned esd_interval;
|
||||
unsigned ulps_timeout;
|
||||
|
||||
bool use_dsi_backlight;
|
||||
|
||||
struct omap_dsi_pin_config pin_config;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct picodlp_panel_data - picodlp panel driver configuration data
|
||||
* @picodlp_adapter_id: i2c_adapter number for picodlp
|
||||
*/
|
||||
struct picodlp_panel_data {
|
||||
int picodlp_adapter_id;
|
||||
int emu_done_gpio;
|
||||
int pwrgood_gpio;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tfp410_platform_data - tfp410 panel driver configuration data
|
||||
* @i2c_bus_num: i2c bus id for the panel
|
||||
* @power_down_gpio: gpio number for PD pin (or -1 if not available)
|
||||
*/
|
||||
struct tfp410_platform_data {
|
||||
int i2c_bus_num;
|
||||
int power_down_gpio;
|
||||
};
|
||||
|
||||
/**
|
||||
* sharp ls panel driver configuration data
|
||||
* @resb_gpio: reset signal
|
||||
* @ini_gpio: power on control
|
||||
* @mo_gpio: selection for resolution(VGA/QVGA)
|
||||
* @lr_gpio: selection for horizontal scanning direction
|
||||
* @ud_gpio: selection for vertical scanning direction
|
||||
*/
|
||||
struct panel_sharp_ls037v7dw01_data {
|
||||
int resb_gpio;
|
||||
int ini_gpio;
|
||||
int mo_gpio;
|
||||
int lr_gpio;
|
||||
int ud_gpio;
|
||||
};
|
||||
|
||||
/**
|
||||
* acx565akm panel driver configuration data
|
||||
* @reset_gpio: reset signal
|
||||
*/
|
||||
struct panel_acx565akm_data {
|
||||
int reset_gpio;
|
||||
};
|
||||
|
||||
/**
|
||||
* nec nl8048 panel driver configuration data
|
||||
* @res_gpio: reset signal
|
||||
* @qvga_gpio: selection for resolution(QVGA/WVGA)
|
||||
*/
|
||||
struct panel_nec_nl8048_data {
|
||||
int res_gpio;
|
||||
int qvga_gpio;
|
||||
};
|
||||
|
||||
/**
|
||||
* tpo td043 panel driver configuration data
|
||||
* @nreset_gpio: reset signal
|
||||
*/
|
||||
struct panel_tpo_td043_data {
|
||||
int nreset_gpio;
|
||||
};
|
||||
|
||||
#endif /* __OMAP_PANEL_DATA_H */
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Header for generic DPI panel driver
|
||||
*
|
||||
* Copyright (C) 2010 Canonical Ltd.
|
||||
* Author: Bryan Wu <bryan.wu@canonical.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 __OMAP_PANEL_GENERIC_DPI_H
|
||||
#define __OMAP_PANEL_GENERIC_DPI_H
|
||||
|
||||
struct omap_dss_device;
|
||||
|
||||
/**
|
||||
* struct panel_generic_dpi_data - panel driver configuration data
|
||||
* @name: panel name
|
||||
* @platform_enable: platform specific panel enable function
|
||||
* @platform_disable: platform specific panel disable function
|
||||
*/
|
||||
struct panel_generic_dpi_data {
|
||||
const char *name;
|
||||
int (*platform_enable)(struct omap_dss_device *dssdev);
|
||||
void (*platform_disable)(struct omap_dss_device *dssdev);
|
||||
};
|
||||
|
||||
#endif /* __OMAP_PANEL_GENERIC_DPI_H */
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef __OMAP_PANEL_N8X0_H
|
||||
#define __OMAP_PANEL_N8X0_H
|
||||
|
||||
struct omap_dss_device;
|
||||
|
||||
struct panel_n8x0_data {
|
||||
int (*platform_enable)(struct omap_dss_device *dssdev);
|
||||
void (*platform_disable)(struct omap_dss_device *dssdev);
|
||||
int panel_reset;
|
||||
int ctrl_pwrdown;
|
||||
|
||||
int (*set_backlight)(struct omap_dss_device *dssdev, int level);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef __OMAP_NOKIA_DSI_PANEL_H
|
||||
#define __OMAP_NOKIA_DSI_PANEL_H
|
||||
|
||||
struct omap_dss_device;
|
||||
|
||||
/**
|
||||
* struct nokia_dsi_panel_data - Nokia DSI panel driver configuration
|
||||
* @name: panel name
|
||||
* @use_ext_te: use external TE
|
||||
* @ext_te_gpio: external TE GPIO
|
||||
* @esd_interval: interval of ESD checks, 0 = disabled (ms)
|
||||
* @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
|
||||
* @use_dsi_backlight: true if panel uses DSI command to control backlight
|
||||
* @pin_config: DSI pin configuration
|
||||
*/
|
||||
struct nokia_dsi_panel_data {
|
||||
const char *name;
|
||||
|
||||
int reset_gpio;
|
||||
|
||||
bool use_ext_te;
|
||||
int ext_te_gpio;
|
||||
|
||||
unsigned esd_interval;
|
||||
unsigned ulps_timeout;
|
||||
|
||||
bool use_dsi_backlight;
|
||||
|
||||
struct omap_dsi_pin_config pin_config;
|
||||
};
|
||||
|
||||
#endif /* __OMAP_NOKIA_DSI_PANEL_H */
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* panel data for picodlp panel
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments
|
||||
*
|
||||
* Author: Mayuresh Janorkar <mayur@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.
|
||||
*/
|
||||
#ifndef __PANEL_PICODLP_H
|
||||
#define __PANEL_PICODLP_H
|
||||
/**
|
||||
* struct : picodlp panel data
|
||||
* picodlp_adapter_id: i2c_adapter number for picodlp
|
||||
*/
|
||||
struct picodlp_panel_data {
|
||||
int picodlp_adapter_id;
|
||||
int emu_done_gpio;
|
||||
int pwrgood_gpio;
|
||||
};
|
||||
#endif /* __PANEL_PICODLP_H */
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Header for TFP410 chip driver
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Inc
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __OMAP_PANEL_TFP410_H
|
||||
#define __OMAP_PANEL_TFP410_H
|
||||
|
||||
struct omap_dss_device;
|
||||
|
||||
/**
|
||||
* struct tfp410_platform_data - panel driver configuration data
|
||||
* @i2c_bus_num: i2c bus id for the panel
|
||||
* @power_down_gpio: gpio number for PD pin (or -1 if not available)
|
||||
*/
|
||||
struct tfp410_platform_data {
|
||||
int i2c_bus_num;
|
||||
int power_down_gpio;
|
||||
};
|
||||
|
||||
#endif /* __OMAP_PANEL_TFP410_H */
|
|
@ -257,10 +257,31 @@ void rfbi_bus_unlock(void);
|
|||
|
||||
/* DSI */
|
||||
|
||||
enum omap_dss_dsi_trans_mode {
|
||||
/* Sync Pulses: both sync start and end packets sent */
|
||||
OMAP_DSS_DSI_PULSE_MODE,
|
||||
/* Sync Events: only sync start packets sent */
|
||||
OMAP_DSS_DSI_EVENT_MODE,
|
||||
/* Burst: only sync start packets sent, pixels are time compressed */
|
||||
OMAP_DSS_DSI_BURST_MODE,
|
||||
};
|
||||
|
||||
struct omap_dss_dsi_videomode_timings {
|
||||
unsigned long hsclk;
|
||||
|
||||
unsigned ndl;
|
||||
unsigned bitspp;
|
||||
|
||||
/* pixels */
|
||||
u16 hact;
|
||||
/* lines */
|
||||
u16 vact;
|
||||
|
||||
/* DSI video mode blanking data */
|
||||
/* Unit: byte clock cycles */
|
||||
u16 hss;
|
||||
u16 hsa;
|
||||
u16 hse;
|
||||
u16 hfp;
|
||||
u16 hbp;
|
||||
/* Unit: line clocks */
|
||||
|
@ -274,14 +295,24 @@ struct omap_dss_dsi_videomode_timings {
|
|||
int hbp_blanking_mode;
|
||||
int hfp_blanking_mode;
|
||||
|
||||
/* Video port sync events */
|
||||
bool vp_vsync_end;
|
||||
bool vp_hsync_end;
|
||||
enum omap_dss_dsi_trans_mode trans_mode;
|
||||
|
||||
bool ddr_clk_always_on;
|
||||
int window_sync;
|
||||
};
|
||||
|
||||
struct omap_dss_dsi_config {
|
||||
enum omap_dss_dsi_mode mode;
|
||||
enum omap_dss_dsi_pixel_format pixel_format;
|
||||
const struct omap_video_timings *timings;
|
||||
|
||||
unsigned long hs_clk_min, hs_clk_max;
|
||||
unsigned long lp_clk_min, lp_clk_max;
|
||||
|
||||
bool ddr_clk_always_on;
|
||||
enum omap_dss_dsi_trans_mode trans_mode;
|
||||
};
|
||||
|
||||
void dsi_bus_lock(struct omap_dss_device *dssdev);
|
||||
void dsi_bus_unlock(struct omap_dss_device *dssdev);
|
||||
int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
|
||||
|
@ -541,9 +572,14 @@ struct omap_dss_writeback_info {
|
|||
struct omap_dss_output {
|
||||
struct list_head list;
|
||||
|
||||
const char *name;
|
||||
|
||||
/* display type supported by the output */
|
||||
enum omap_display_type type;
|
||||
|
||||
/* DISPC channel for this output */
|
||||
enum omap_channel dispc_channel;
|
||||
|
||||
/* output instance */
|
||||
enum omap_dss_output_id id;
|
||||
|
||||
|
@ -561,6 +597,7 @@ struct omap_dss_device {
|
|||
|
||||
enum omap_display_type type;
|
||||
|
||||
/* obsolete, to be removed */
|
||||
enum omap_channel channel;
|
||||
|
||||
union {
|
||||
|
@ -590,41 +627,11 @@ struct omap_dss_device {
|
|||
} venc;
|
||||
} phy;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
u16 lck_div;
|
||||
u16 pck_div;
|
||||
enum omap_dss_clk_source lcd_clk_src;
|
||||
} channel;
|
||||
|
||||
enum omap_dss_clk_source dispc_fclk_src;
|
||||
} dispc;
|
||||
|
||||
struct {
|
||||
/* regn is one greater than TRM's REGN value */
|
||||
u16 regn;
|
||||
u16 regm;
|
||||
u16 regm_dispc;
|
||||
u16 regm_dsi;
|
||||
|
||||
u16 lp_clk_div;
|
||||
enum omap_dss_clk_source dsi_fclk_src;
|
||||
} dsi;
|
||||
|
||||
struct {
|
||||
/* regn is one greater than TRM's REGN value */
|
||||
u16 regn;
|
||||
u16 regm2;
|
||||
} hdmi;
|
||||
} clocks;
|
||||
|
||||
struct {
|
||||
struct omap_video_timings timings;
|
||||
|
||||
enum omap_dss_dsi_pixel_format dsi_pix_fmt;
|
||||
enum omap_dss_dsi_mode dsi_mode;
|
||||
struct omap_dss_dsi_videomode_timings dsi_vm_timings;
|
||||
} panel;
|
||||
|
||||
struct {
|
||||
|
@ -829,15 +836,8 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
|
|||
void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
|
||||
bool enable);
|
||||
int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
|
||||
void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
|
||||
void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_dsi_pixel_format fmt);
|
||||
void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_dsi_mode mode);
|
||||
void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_dss_dsi_videomode_timings *timings);
|
||||
int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
|
||||
const struct omap_dss_dsi_config *config);
|
||||
|
||||
int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
|
||||
void (*callback)(int, void *), void *data);
|
||||
|
@ -846,8 +846,6 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
|
|||
void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
|
||||
int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
|
||||
const struct omap_dsi_pin_config *pin_cfg);
|
||||
int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
|
||||
unsigned long ddr_clk, unsigned long lp_clk);
|
||||
|
||||
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
|
||||
|
|
Loading…
Reference in New Issue