Commit dea14dfa authored by Dave Airlie's avatar Dave Airlie

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
  ...
parents e4fda9f2 3d62fe5b
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include "gpmc-smc91x.h" #include "gpmc-smc91x.h"
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
#include "mux.h" #include "mux.h"
#include "hsmmc.h" #include "hsmmc.h"
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "common.h" #include "common.h"
#include <linux/omap-dma.h> #include <linux/omap-dma.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-tfp410.h> #include <video/omap-panel-data.h>
#include "gpmc.h" #include "gpmc.h"
#include "gpmc-smc91x.h" #include "gpmc-smc91x.h"
......
...@@ -35,8 +35,7 @@ ...@@ -35,8 +35,7 @@
#include "common.h" #include "common.h"
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
#include <video/omap-panel-tfp410.h>
#include "am35xx-emac.h" #include "am35xx-emac.h"
#include "mux.h" #include "mux.h"
......
...@@ -41,8 +41,7 @@ ...@@ -41,8 +41,7 @@
#include <linux/platform_data/mtd-nand-omap2.h> #include <linux/platform_data/mtd-nand-omap2.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
#include <video/omap-panel-tfp410.h>
#include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/platform_data/spi-omap2-mcspi.h>
#include "common.h" #include "common.h"
......
...@@ -43,8 +43,7 @@ ...@@ -43,8 +43,7 @@
#include "gpmc.h" #include "gpmc.h"
#include <linux/platform_data/mtd-nand-omap2.h> #include <linux/platform_data/mtd-nand-omap2.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
#include <video/omap-panel-tfp410.h>
#include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/input/matrix_keypad.h> #include <linux/input/matrix_keypad.h>
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
#include "common.h" #include "common.h"
#include "mux.h" #include "mux.h"
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <video/omapdss.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 <linux/platform_data/mtd-onenand-omap2.h>
#include "common.h" #include "common.h"
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#include "gpmc-smsc911x.h" #include "gpmc-smsc911x.h"
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
#include "board-flash.h" #include "board-flash.h"
#include "mux.h" #include "mux.h"
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <video/omapdss.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 <linux/platform_data/mtd-nand-omap2.h>
#include "common.h" #include "common.h"
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#include "common.h" #include "common.h"
#include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/platform_data/spi-omap2-mcspi.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-tfp410.h> #include <video/omap-panel-data.h>
#include "soc.h" #include "soc.h"
#include "mux.h" #include "mux.h"
......
...@@ -44,8 +44,7 @@ ...@@ -44,8 +44,7 @@
#include "gpmc.h" #include "gpmc.h"
#include <linux/platform_data/mtd-nand-omap2.h> #include <linux/platform_data/mtd-nand-omap2.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
#include <video/omap-panel-tfp410.h>
#include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/platform_data/spi-omap2-mcspi.h>
......
...@@ -47,8 +47,7 @@ ...@@ -47,8 +47,7 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
#include <video/omap-panel-tfp410.h>
#include "common.h" #include "common.h"
#include "mux.h" #include "mux.h"
......
...@@ -27,9 +27,7 @@ ...@@ -27,9 +27,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-tfp410.h> #include <video/omap-panel-data.h>
#include <video/omap-panel-nokia-dsi.h>
#include <video/omap-panel-picodlp.h>
#include "soc.h" #include "soc.h"
#include "dss-common.h" #include "dss-common.h"
......
...@@ -110,6 +110,11 @@ static enum drm_connector_status omap_connector_detect( ...@@ -110,6 +110,11 @@ static enum drm_connector_status omap_connector_detect(
ret = connector_status_connected; ret = connector_status_connected;
else else
ret = connector_status_disconnected; 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 { } else {
ret = connector_status_unknown; ret = connector_status_unknown;
} }
...@@ -189,12 +194,30 @@ static int omap_connector_mode_valid(struct drm_connector *connector, ...@@ -189,12 +194,30 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
struct omap_video_timings timings = {0}; struct omap_video_timings timings = {0};
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_display_mode *new_mode; struct drm_display_mode *new_mode;
int ret = MODE_BAD; int r, ret = MODE_BAD;
copy_timings_drm_to_omap(&timings, mode); copy_timings_drm_to_omap(&timings, mode);
mode->vrefresh = drm_mode_vrefresh(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 */ /* check if vrefresh is still valid */
new_mode = drm_mode_duplicate(dev, mode); new_mode = drm_mode_duplicate(dev, mode);
new_mode->clock = timings.pixel_clock; new_mode->clock = timings.pixel_clock;
......
...@@ -74,6 +74,13 @@ struct omap_crtc { ...@@ -74,6 +74,13 @@ struct omap_crtc {
struct work_struct page_flip_work; 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 * Manager-ops, callbacks from output when they need to configure
* the upstream part of the video pipe. * the upstream part of the video pipe.
...@@ -613,7 +620,13 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, ...@@ -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.pre_apply = omap_crtc_pre_apply;
omap_crtc->apply.post_apply = omap_crtc_post_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->apply_irq.irq = omap_crtc_apply_irq;
omap_crtc->error_irq.irqmask = omap_crtc->error_irq.irqmask =
...@@ -621,12 +634,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, ...@@ -621,12 +634,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
omap_crtc->error_irq.irq = omap_crtc_error_irq; omap_crtc->error_irq.irq = omap_crtc_error_irq;
omap_irq_register(dev, &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: */ /* temporary: */
omap_crtc->mgr.id = channel; omap_crtc->mgr.id = channel;
......
...@@ -74,54 +74,53 @@ static int get_connector_type(struct omap_dss_device *dssdev) ...@@ -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) static int omap_modeset_init(struct drm_device *dev)
{ {
struct omap_drm_private *priv = dev->dev_private; struct omap_drm_private *priv = dev->dev_private;
struct omap_dss_device *dssdev = NULL; struct omap_dss_device *dssdev = NULL;
int num_ovls = dss_feat_get_num_ovls(); 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); drm_mode_config_init(dev);
omap_drm_irq_install(dev); omap_drm_irq_install(dev);
/* /*
* Create private planes and CRTCs for the last NUM_CRTCs overlay * We usually don't want to create a CRTC for each manager, at least
* plus manager: * 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++) { num_crtcs = min3(num_crtc, num_mgrs, num_ovls);
struct drm_plane *plane;
struct drm_crtc *crtc;
plane = omap_plane_init(dev, id, true); dssdev = NULL;
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;
}
for_each_dss_dev(dssdev) { for_each_dss_dev(dssdev) {
struct drm_connector *connector; struct drm_connector *connector;
struct drm_encoder *encoder; struct drm_encoder *encoder;
enum omap_channel channel;
if (!dssdev->driver) { if (!dssdev->driver) {
dev_warn(dev->dev, "%s has no driver.. skipping it\n", dev_warn(dev->dev, "%s has no driver.. skipping it\n",
dssdev->name); dssdev->name);
return 0; continue;
} }
if (!(dssdev->driver->get_timings || if (!(dssdev->driver->get_timings ||
...@@ -129,7 +128,7 @@ static int omap_modeset_init(struct drm_device *dev) ...@@ -129,7 +128,7 @@ static int omap_modeset_init(struct drm_device *dev)
dev_warn(dev->dev, "%s driver does not support " dev_warn(dev->dev, "%s driver does not support "
"get_timings or read_edid.. skipping it!\n", "get_timings or read_edid.. skipping it!\n",
dssdev->name); dssdev->name);
return 0; continue;
} }
encoder = omap_encoder_init(dev, dssdev); encoder = omap_encoder_init(dev, dssdev);
...@@ -157,16 +156,118 @@ static int omap_modeset_init(struct drm_device *dev) ...@@ -157,16 +156,118 @@ static int omap_modeset_init(struct drm_device *dev)
drm_mode_connector_attach_encoder(connector, encoder); 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: */ /* figure out which crtc's we can connect the encoder to: */
encoder->possible_crtcs = 0; encoder->possible_crtcs = 0;
for (id = 0; id < priv->num_crtcs; id++) { for (id = 0; id < priv->num_crtcs; id++) {
enum omap_dss_output_id supported_outputs = struct drm_crtc *crtc = priv->crtcs[id];
dss_feat_get_supported_outputs(pipe2chan(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) if (supported_outputs & dssdev->output->id)
encoder->possible_crtcs |= (1 << 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_width = 32;
dev->mode_config.min_height = 32; dev->mode_config.min_height = 32;
...@@ -303,7 +404,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data, ...@@ -303,7 +404,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
return ret; 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_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_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), 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 = { ...@@ -567,7 +668,7 @@ static const struct dev_pm_ops omapdrm_pm_ops = {
}; };
#endif #endif
struct platform_driver pdev = { static struct platform_driver pdev = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -139,8 +139,8 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); ...@@ -139,8 +139,8 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
int omap_gem_resume(struct device *dev); int omap_gem_resume(struct device *dev);
#endif #endif
int omap_irq_enable_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); void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id);
irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
void omap_irq_preinstall(struct drm_device *dev); void omap_irq_preinstall(struct drm_device *dev);
int omap_irq_postinstall(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) ...@@ -271,39 +271,9 @@ static inline int align_pitch(int pitch, int width, int bpp)
return ALIGN(pitch, 8 * bytespp); 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 */ /* map crtc to vblank mask */
static inline uint32_t pipe2vbl(int crtc) uint32_t pipe2vbl(struct drm_crtc *crtc);
{ struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);
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;
}
/* should these be made into common util helpers? /* should these be made into common util helpers?
*/ */
......
...@@ -41,6 +41,13 @@ struct omap_encoder { ...@@ -41,6 +41,13 @@ struct omap_encoder {
struct omap_dss_device *dssdev; 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) static void omap_encoder_destroy(struct drm_encoder *encoder)
{ {
struct omap_encoder *omap_encoder = to_omap_encoder(encoder); struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
...@@ -128,12 +135,25 @@ int omap_encoder_update(struct drm_encoder *encoder, ...@@ -128,12 +135,25 @@ int omap_encoder_update(struct drm_encoder *encoder,
dssdev->output->manager = mgr; dssdev->output->manager = mgr;
if (dssdrv->check_timings) {
ret = dssdrv->check_timings(dssdev, 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) { if (ret) {
dev_err(dev->dev, "could not set timings: %d\n", ret); dev_err(dev->dev, "could not set timings: %d\n", ret);
return ret; return ret;
} }
if (dssdrv->set_timings)
dssdrv->set_timings(dssdev, timings); dssdrv->set_timings(dssdev, timings);
return 0; return 0;
......
...@@ -178,7 +178,7 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer, ...@@ -178,7 +178,7 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
return omap_gem_mmap_obj(obj, vma); return omap_gem_mmap_obj(obj, vma);
} }
struct dma_buf_ops omap_dmabuf_ops = { static struct dma_buf_ops omap_dmabuf_ops = {
.map_dma_buf = omap_gem_map_dma_buf, .map_dma_buf = omap_gem_map_dma_buf,
.unmap_dma_buf = omap_gem_unmap_dma_buf, .unmap_dma_buf = omap_gem_unmap_dma_buf,
.release = omap_gem_dmabuf_release, .release = omap_gem_dmabuf_release,
......
...@@ -130,12 +130,13 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, ...@@ -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 * Zero on success, appropriate errno if the given @crtc's vblank
* interrupt cannot be enabled. * 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 omap_drm_private *priv = dev->dev_private;
struct drm_crtc *crtc = priv->crtcs[crtc_id];
unsigned long flags; unsigned long flags;
DBG("dev=%p, crtc=%d", dev, crtc); DBG("dev=%p, crtc=%d", dev, crtc_id);
dispc_runtime_get(); dispc_runtime_get();
spin_lock_irqsave(&list_lock, flags); spin_lock_irqsave(&list_lock, flags);
...@@ -156,12 +157,13 @@ int omap_irq_enable_vblank(struct drm_device *dev, int crtc) ...@@ -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 * a hardware vblank counter, this routine should be a no-op, since
* interrupts will have to stay on to keep the count accurate. * 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 omap_drm_private *priv = dev->dev_private;
struct drm_crtc *crtc = priv->crtcs[crtc_id];
unsigned long flags; unsigned long flags;
DBG("dev=%p, crtc=%d", dev, crtc); DBG("dev=%p, crtc=%d", dev, crtc_id);
dispc_runtime_get(); dispc_runtime_get();
spin_lock_irqsave(&list_lock, flags); spin_lock_irqsave(&list_lock, flags);
...@@ -186,9 +188,12 @@ irqreturn_t omap_irq_handler(DRM_IRQ_ARGS) ...@@ -186,9 +188,12 @@ irqreturn_t omap_irq_handler(DRM_IRQ_ARGS)
VERB("irqs: %08x", irqstatus); VERB("irqs: %08x", irqstatus);
for (id = 0; id < priv->num_crtcs; id++) for (id = 0; id < priv->num_crtcs; id++) {
if (irqstatus & pipe2vbl(id)) struct drm_crtc *crtc = priv->crtcs[id];
if (irqstatus & pipe2vbl(crtc))
drm_handle_vblank(dev, id); drm_handle_vblank(dev, id);
}
spin_lock_irqsave(&list_lock, flags); spin_lock_irqsave(&list_lock, flags);
list_for_each_entry_safe(handler, n, &priv->irq_list, node) { list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
......
...@@ -247,6 +247,12 @@ static int omap_plane_update(struct drm_plane *plane, ...@@ -247,6 +247,12 @@ static int omap_plane_update(struct drm_plane *plane,
{ {
struct omap_plane *omap_plane = to_omap_plane(plane); struct omap_plane *omap_plane = to_omap_plane(plane);
omap_plane->enabled = true; omap_plane->enabled = true;
if (plane->fb)
drm_framebuffer_unreference(plane->fb);
drm_framebuffer_reference(fb);
return omap_plane_mode_set(plane, crtc, fb, return omap_plane_mode_set(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h, crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h, src_x, src_y, src_w, src_h,
......
...@@ -29,8 +29,10 @@ ...@@ -29,8 +29,10 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/backlight.h> #include <linux/backlight.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/gpio.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-data.h>
#define MIPID_CMD_READ_DISP_ID 0x04 #define MIPID_CMD_READ_DISP_ID 0x04
#define MIPID_CMD_READ_RED 0x06 #define MIPID_CMD_READ_RED 0x06
...@@ -336,8 +338,6 @@ static int acx565akm_bl_update_status(struct backlight_device *dev) ...@@ -336,8 +338,6 @@ static int acx565akm_bl_update_status(struct backlight_device *dev)
r = 0; r = 0;
if (md->has_bc) if (md->has_bc)
acx565akm_set_brightness(md, level); acx565akm_set_brightness(md, level);
else if (md->dssdev->set_backlight)
r = md->dssdev->set_backlight(md->dssdev, level);
else else
r = -ENODEV; r = -ENODEV;
...@@ -352,7 +352,7 @@ static int acx565akm_bl_get_intensity(struct backlight_device *dev) ...@@ -352,7 +352,7 @@ static int acx565akm_bl_get_intensity(struct backlight_device *dev)
dev_dbg(&dev->dev, "%s\n", __func__); dev_dbg(&dev->dev, "%s\n", __func__);
if (!md->has_bc && md->dssdev->set_backlight == NULL) if (!md->has_bc)
return -ENODEV; return -ENODEV;
if (dev->props.fb_blank == FB_BLANK_UNBLANK && if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
...@@ -496,21 +496,38 @@ static struct omap_video_timings acx_panel_timings = { ...@@ -496,21 +496,38 @@ static struct omap_video_timings acx_panel_timings = {
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, .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) static int acx_panel_probe(struct omap_dss_device *dssdev)
{ {
int r; int r;
struct acx565akm_device *md = &acx_dev; struct acx565akm_device *md = &acx_dev;
struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
struct backlight_device *bldev; struct backlight_device *bldev;
int max_brightness, brightness; int max_brightness, brightness;
struct backlight_properties props; struct backlight_properties props;
dev_dbg(&dssdev->dev, "%s\n", __func__); dev_dbg(&dssdev->dev, "%s\n", __func__);
if (!panel_data)
return -EINVAL;
/* FIXME AC bias ? */ /* FIXME AC bias ? */
dssdev->panel.timings = acx_panel_timings; dssdev->panel.timings = acx_panel_timings;
if (dssdev->platform_enable) if (gpio_is_valid(panel_data->reset_gpio)) {
dssdev->platform_enable(dssdev); 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 * After reset we have to wait 5 msec before the first
* command can be sent. * command can be sent.
...@@ -522,8 +539,9 @@ static int acx_panel_probe(struct omap_dss_device *dssdev) ...@@ -522,8 +539,9 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
r = panel_detect(md); r = panel_detect(md);
if (r) { if (r) {
dev_err(&dssdev->dev, "%s panel detect error\n", __func__); dev_err(&dssdev->dev, "%s panel detect error\n", __func__);
if (!md->enabled && dssdev->platform_disable) if (!md->enabled && gpio_is_valid(panel_data->reset_gpio))
dssdev->platform_disable(dssdev); gpio_set_value(panel_data->reset_gpio, 0);
return r; return r;
} }
...@@ -532,8 +550,8 @@ static int acx_panel_probe(struct omap_dss_device *dssdev) ...@@ -532,8 +550,8 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
mutex_unlock(&acx_dev.mutex); mutex_unlock(&acx_dev.mutex);
if (!md->enabled) { if (!md->enabled) {
if (dssdev->platform_disable) if (gpio_is_valid(panel_data->reset_gpio))
dssdev->platform_disable(dssdev); gpio_set_value(panel_data->reset_gpio, 0);
} }
/*------- Backlight control --------*/ /*------- Backlight control --------*/
...@@ -557,15 +575,10 @@ static int acx_panel_probe(struct omap_dss_device *dssdev) ...@@ -557,15 +575,10 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
md->cabc_mode = get_hw_cabc_mode(md); md->cabc_mode = get_hw_cabc_mode(md);
} }
if (md->has_bc)
max_brightness = 255; max_brightness = 255;
else
max_brightness = dssdev->max_backlight_level;
if (md->has_bc) if (md->has_bc)
brightness = acx565akm_get_actual_brightness(md); brightness = acx565akm_get_actual_brightness(md);
else if (dssdev->get_backlight)
brightness = dssdev->get_backlight(dssdev);
else else
brightness = 0; brightness = 0;
...@@ -591,6 +604,7 @@ static void acx_panel_remove(struct omap_dss_device *dssdev) ...@@ -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) static int acx_panel_power_on(struct omap_dss_device *dssdev)
{ {
struct acx565akm_device *md = &acx_dev; struct acx565akm_device *md = &acx_dev;
struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
int r; int r;
dev_dbg(&dssdev->dev, "%s\n", __func__); dev_dbg(&dssdev->dev, "%s\n", __func__);
...@@ -612,11 +626,8 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev) ...@@ -612,11 +626,8 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
/*FIXME tweak me */ /*FIXME tweak me */
msleep(50); msleep(50);
if (dssdev->platform_enable) { if (gpio_is_valid(panel_data->reset_gpio))
r = dssdev->platform_enable(dssdev); gpio_set_value(panel_data->reset_gpio, 1);
if (r)
goto fail;
}
if (md->enabled) { if (md->enabled) {
dev_dbg(&md->spi->dev, "panel already enabled\n"); dev_dbg(&md->spi->dev, "panel already enabled\n");
...@@ -645,8 +656,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev) ...@@ -645,8 +656,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
mutex_unlock(&md->mutex); mutex_unlock(&md->mutex);
return acx565akm_bl_update_status(md->bl_dev); return acx565akm_bl_update_status(md->bl_dev);
fail:
omapdss_sdi_display_disable(dssdev);
fail_unlock: fail_unlock:
mutex_unlock(&md->mutex); mutex_unlock(&md->mutex);
return r; return r;
...@@ -655,6 +665,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev) ...@@ -655,6 +665,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
static void acx_panel_power_off(struct omap_dss_device *dssdev) static void acx_panel_power_off(struct omap_dss_device *dssdev)
{ {
struct acx565akm_device *md = &acx_dev; struct acx565akm_device *md = &acx_dev;
struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
dev_dbg(&dssdev->dev, "%s\n", __func__); dev_dbg(&dssdev->dev, "%s\n", __func__);
...@@ -678,8 +689,8 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev) ...@@ -678,8 +689,8 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev)
*/ */
msleep(50); msleep(50);
if (dssdev->platform_disable) if (gpio_is_valid(panel_data->reset_gpio))
dssdev->platform_disable(dssdev); gpio_set_value(panel_data->reset_gpio, 0);
/* FIXME need to tweak this delay */ /* FIXME need to tweak this delay */
msleep(100); msleep(100);
......
...@@ -33,9 +33,10 @@ ...@@ -33,9 +33,10 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-data.h>
struct panel_config { struct panel_config {
struct omap_video_timings timings; struct omap_video_timings timings;
...@@ -533,7 +534,7 @@ static inline struct panel_generic_dpi_data ...@@ -533,7 +534,7 @@ static inline struct panel_generic_dpi_data
static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) 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_generic_dpi_data *panel_data = get_panel_data(dssdev);
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
struct panel_config *panel_config = drv_data->panel_config; 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) ...@@ -552,15 +553,13 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
if (panel_config->power_on_delay) if (panel_config->power_on_delay)
msleep(panel_config->power_on_delay); msleep(panel_config->power_on_delay);
if (panel_data->platform_enable) { for (i = 0; i < panel_data->num_gpios; ++i) {
r = panel_data->platform_enable(dssdev); gpio_set_value_cansleep(panel_data->gpios[i],
if (r) panel_data->gpio_invert[i] ? 0 : 1);
goto err1;
} }
return 0; return 0;
err1:
omapdss_dpi_display_disable(dssdev);
err0: err0:
return r; return r;
} }
...@@ -570,12 +569,15 @@ static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev) ...@@ -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_generic_dpi_data *panel_data = get_panel_data(dssdev);
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
struct panel_config *panel_config = drv_data->panel_config; struct panel_config *panel_config = drv_data->panel_config;
int i;
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return; return;
if (panel_data->platform_disable) for (i = panel_data->num_gpios - 1; i >= 0; --i) {
panel_data->platform_disable(dssdev); gpio_set_value_cansleep(panel_data->gpios[i],
panel_data->gpio_invert[i] ? 1 : 0);
}
/* wait couple of vsyncs after disabling the LCD */ /* wait couple of vsyncs after disabling the LCD */
if (panel_config->power_off_delay) if (panel_config->power_off_delay)
...@@ -589,7 +591,7 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) ...@@ -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_generic_dpi_data *panel_data = get_panel_data(dssdev);
struct panel_config *panel_config = NULL; struct panel_config *panel_config = NULL;
struct panel_drv_data *drv_data = NULL; struct panel_drv_data *drv_data = NULL;
int i; int i, r;
dev_dbg(&dssdev->dev, "probe\n"); dev_dbg(&dssdev->dev, "probe\n");
...@@ -606,9 +608,18 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) ...@@ -606,9 +608,18 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
if (!panel_config) if (!panel_config)
return -EINVAL; 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; 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) if (!drv_data)
return -ENOMEM; return -ENOMEM;
...@@ -624,12 +635,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) ...@@ -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) 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"); dev_dbg(&dssdev->dev, "remove\n");
kfree(drv_data);
dev_set_drvdata(&dssdev->dev, NULL); dev_set_drvdata(&dssdev->dev, NULL);
} }
......
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/gpio.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-data.h>
struct lb035q02_data { struct lb035q02_data {
struct mutex lock; struct mutex lock;
...@@ -48,9 +50,16 @@ static struct omap_video_timings lb035q02_timings = { ...@@ -48,9 +50,16 @@ static struct omap_video_timings lb035q02_timings = {
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, .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) 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) if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0; return 0;
...@@ -62,54 +71,65 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) ...@@ -62,54 +71,65 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
if (r) if (r)
goto err0; goto err0;
if (dssdev->platform_enable) { for (i = 0; i < panel_data->num_gpios; ++i) {
r = dssdev->platform_enable(dssdev); gpio_set_value_cansleep(panel_data->gpios[i],
if (r) panel_data->gpio_invert[i] ? 0 : 1);
goto err1;
} }
return 0; return 0;
err1:
omapdss_dpi_display_disable(dssdev);
err0: err0:
return r; return r;
} }
static void lb035q02_panel_power_off(struct omap_dss_device *dssdev) 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) if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return; return;
if (dssdev->platform_disable) for (i = panel_data->num_gpios - 1; i >= 0; --i) {
dssdev->platform_disable(dssdev); gpio_set_value_cansleep(panel_data->gpios[i],
panel_data->gpio_invert[i] ? 1 : 0);
}
omapdss_dpi_display_disable(dssdev); omapdss_dpi_display_disable(dssdev);
} }
static int lb035q02_panel_probe(struct omap_dss_device *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; struct lb035q02_data *ld;
int r; int r, i;
if (!panel_data)
return -EINVAL;
dssdev->panel.timings = lb035q02_timings; dssdev->panel.timings = lb035q02_timings;
ld = kzalloc(sizeof(*ld), GFP_KERNEL); ld = devm_kzalloc(&dssdev->dev, sizeof(*ld), GFP_KERNEL);
if (!ld) { if (!ld)
r = -ENOMEM; return -ENOMEM;
goto err;
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); mutex_init(&ld->lock);
dev_set_drvdata(&dssdev->dev, ld); dev_set_drvdata(&dssdev->dev, ld);
return 0; return 0;
err:
return r;
} }
static void lb035q02_panel_remove(struct omap_dss_device *dssdev) 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) static int lb035q02_panel_enable(struct omap_dss_device *dssdev)
......
...@@ -5,11 +5,10 @@ ...@@ -5,11 +5,10 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/backlight.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-n8x0.h> #include <video/omap-panel-data.h>
#define BLIZZARD_REV_CODE 0x00 #define BLIZZARD_REV_CODE 0x00
#define BLIZZARD_CONFIG 0x02 #define BLIZZARD_CONFIG 0x02
...@@ -69,7 +68,6 @@ static struct panel_drv_data { ...@@ -69,7 +68,6 @@ static struct panel_drv_data {
struct omap_dss_device *dssdev; struct omap_dss_device *dssdev;
struct spi_device *spidev; struct spi_device *spidev;
struct backlight_device *bldev;
int blizzard_ver; int blizzard_ver;
} s_drv_data; } s_drv_data;
...@@ -297,12 +295,6 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev) ...@@ -297,12 +295,6 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
gpio_direction_output(bdata->ctrl_pwrdown, 1); 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, omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
dssdev->panel.timings.y_res); dssdev->panel.timings.y_res);
omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size); omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
...@@ -375,9 +367,6 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev) ...@@ -375,9 +367,6 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
err_inv_chip: err_inv_chip:
omapdss_rfbi_display_disable(dssdev); omapdss_rfbi_display_disable(dssdev);
err_rfbi_en: err_rfbi_en:
if (bdata->platform_disable)
bdata->platform_disable(dssdev);
err_plat_en:
gpio_direction_output(bdata->ctrl_pwrdown, 0); gpio_direction_output(bdata->ctrl_pwrdown, 0);
return r; return r;
} }
...@@ -394,9 +383,6 @@ static void n8x0_panel_power_off(struct omap_dss_device *dssdev) ...@@ -394,9 +383,6 @@ static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
send_display_off(spi); send_display_off(spi);
send_sleep_in(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 * 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 * 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 = { ...@@ -424,54 +410,10 @@ static const struct rfbi_timings n8x0_panel_timings = {
.cs_pulse_width = 0, .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) static int n8x0_panel_probe(struct omap_dss_device *dssdev)
{ {
struct panel_n8x0_data *bdata = get_board_data(dssdev); struct panel_n8x0_data *bdata = get_board_data(dssdev);
struct panel_drv_data *ddata; struct panel_drv_data *ddata;
struct backlight_device *bldev;
struct backlight_properties props;
int r; int r;
dev_dbg(&dssdev->dev, "probe\n"); dev_dbg(&dssdev->dev, "probe\n");
...@@ -491,40 +433,27 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev) ...@@ -491,40 +433,27 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
dssdev->ctrl.rfbi_timings = n8x0_panel_timings; dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
memset(&props, 0, sizeof(props)); if (gpio_is_valid(bdata->panel_reset)) {
props.max_brightness = 127; r = devm_gpio_request_one(&dssdev->dev, bdata->panel_reset,
props.type = BACKLIGHT_PLATFORM; GPIOF_OUT_INIT_LOW, "PANEL RESET");
bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, if (r)
dssdev, &n8x0_bl_ops, &props);
if (IS_ERR(bldev)) {
r = PTR_ERR(bldev);
dev_err(&dssdev->dev, "register backlight failed\n");
return r; return r;
} }
ddata->bldev = bldev; if (gpio_is_valid(bdata->ctrl_pwrdown)) {
r = devm_gpio_request_one(&dssdev->dev, bdata->ctrl_pwrdown,
bldev->props.fb_blank = FB_BLANK_UNBLANK; GPIOF_OUT_INIT_LOW, "PANEL PWRDOWN");
bldev->props.power = FB_BLANK_UNBLANK; if (r)
bldev->props.brightness = 127; return r;
}
n8x0_bl_update_status(bldev);
return 0; return 0;
} }
static void n8x0_panel_remove(struct omap_dss_device *dssdev) 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"); 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); dev_set_drvdata(&dssdev->dev, NULL);
} }
......
...@@ -19,10 +19,11 @@ ...@@ -19,10 +19,11 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/backlight.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/gpio.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-data.h>
#define LCD_XRES 800 #define LCD_XRES 800
#define LCD_YRES 480 #define LCD_YRES 480
...@@ -32,10 +33,6 @@ ...@@ -32,10 +33,6 @@
*/ */
#define LCD_PIXEL_CLOCK 23800 #define LCD_PIXEL_CLOCK 23800
struct nec_8048_data {
struct backlight_device *bl;
};
static const struct { static const struct {
unsigned char addr; unsigned char addr;
unsigned char dat; unsigned char dat;
...@@ -84,93 +81,47 @@ static struct omap_video_timings nec_8048_panel_timings = { ...@@ -84,93 +81,47 @@ static struct omap_video_timings nec_8048_panel_timings = {
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .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);
}
static int nec_8048_bl_get_brightness(struct backlight_device *bl)
{ {
if (bl->props.fb_blank == FB_BLANK_UNBLANK && return (struct panel_nec_nl8048_data *) dssdev->data;
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) static int nec_8048_panel_probe(struct omap_dss_device *dssdev)
{ {
struct backlight_device *bl; struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
struct nec_8048_data *necd;
struct backlight_properties props;
int r; int r;
dssdev->panel.timings = nec_8048_panel_timings; if (!pd)
return -EINVAL;
necd = kzalloc(sizeof(*necd), GFP_KERNEL);
if (!necd)
return -ENOMEM;
dev_set_drvdata(&dssdev->dev, necd);
memset(&props, 0, sizeof(struct backlight_properties)); dssdev->panel.timings = nec_8048_panel_timings;
props.max_brightness = 255;
bl = backlight_device_register("nec-8048", &dssdev->dev, dssdev, if (gpio_is_valid(pd->qvga_gpio)) {
&nec_8048_bl_ops, &props); r = devm_gpio_request_one(&dssdev->dev, pd->qvga_gpio,
if (IS_ERR(bl)) { GPIOF_OUT_INIT_HIGH, "lcd QVGA");
r = PTR_ERR(bl); if (r)
kfree(necd);
return 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 (gpio_is_valid(pd->res_gpio)) {
if (r < 0) r = devm_gpio_request_one(&dssdev->dev, pd->res_gpio,
dev_err(&dssdev->dev, "failed to set lcd brightness\n"); GPIOF_OUT_INIT_LOW, "lcd RES");
if (r)
return r;
}
return 0; return 0;
} }
static void nec_8048_panel_remove(struct omap_dss_device *dssdev) 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) static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
{ {
struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
int r; 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) if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0; return 0;
...@@ -182,36 +133,24 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev) ...@@ -182,36 +133,24 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
if (r) if (r)
goto err0; goto err0;
if (dssdev->platform_enable) { if (gpio_is_valid(pd->res_gpio))
r = dssdev->platform_enable(dssdev); gpio_set_value_cansleep(pd->res_gpio, 1);
if (r)
goto err1;
}
r = nec_8048_bl_update_status(bl);
if (r < 0)
dev_err(&dssdev->dev, "failed to set lcd brightness\n");
return 0; return 0;
err1:
omapdss_dpi_display_disable(dssdev);
err0: err0:
return r; return r;
} }
static void nec_8048_panel_power_off(struct omap_dss_device *dssdev) static void nec_8048_panel_power_off(struct omap_dss_device *dssdev)
{ {
struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
struct backlight_device *bl = necd->bl;
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return; return;
bl->props.brightness = 0; if (gpio_is_valid(pd->res_gpio))
nec_8048_bl_update_status(bl); gpio_set_value_cansleep(pd->res_gpio, 0);
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
omapdss_dpi_display_disable(dssdev); omapdss_dpi_display_disable(dssdev);
} }
...@@ -303,16 +242,22 @@ static int nec_8048_spi_remove(struct spi_device *spi) ...@@ -303,16 +242,22 @@ static int nec_8048_spi_remove(struct spi_device *spi)
return 0; 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); nec_8048_spi_send(spi, 2, 0x01);
mdelay(40); mdelay(40);
return 0; 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 */ /* reinitialize the panel */
spi_setup(spi); spi_setup(spi);
nec_8048_spi_send(spi, 2, 0x00); nec_8048_spi_send(spi, 2, 0x00);
...@@ -321,14 +266,20 @@ static int nec_8048_spi_resume(struct spi_device *spi) ...@@ -321,14 +266,20 @@ static int nec_8048_spi_resume(struct spi_device *spi)
return 0; 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 = { static struct spi_driver nec_8048_spi_driver = {
.probe = nec_8048_spi_probe, .probe = nec_8048_spi_probe,
.remove = nec_8048_spi_remove, .remove = nec_8048_spi_remove,
.suspend = nec_8048_spi_suspend,
.resume = nec_8048_spi_resume,
.driver = { .driver = {
.name = "nec_8048_spi", .name = "nec_8048_spi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = NEC_8048_SPI_PM_OPS,
}, },
}; };
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-picodlp.h> #include <video/omap-panel-data.h>
#include "panel-picodlp.h" #include "panel-picodlp.h"
...@@ -354,12 +354,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev) ...@@ -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_data *picod = dev_get_drvdata(&dssdev->dev);
struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); 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); gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
msleep(1); msleep(1);
gpio_set_value(picodlp_pdata->pwrgood_gpio, 1); gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
...@@ -398,9 +392,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev) ...@@ -398,9 +392,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
err: err:
omapdss_dpi_display_disable(dssdev); omapdss_dpi_display_disable(dssdev);
err1: err1:
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
return r; return r;
} }
...@@ -412,9 +403,6 @@ static void picodlp_panel_power_off(struct omap_dss_device *dssdev) ...@@ -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->emu_done_gpio, 0);
gpio_set_value(picodlp_pdata->pwrgood_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) static int picodlp_panel_probe(struct omap_dss_device *dssdev)
...@@ -423,11 +411,14 @@ 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 picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
struct i2c_client *picodlp_i2c_client; struct i2c_client *picodlp_i2c_client;
int r = 0, picodlp_adapter_id; int r, picodlp_adapter_id;
dssdev->panel.timings = pico_ls_timings; 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) if (!picod)
return -ENOMEM; return -ENOMEM;
...@@ -438,25 +429,37 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev) ...@@ -438,25 +429,37 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev)
adapter = i2c_get_adapter(picodlp_adapter_id); adapter = i2c_get_adapter(picodlp_adapter_id);
if (!adapter) { if (!adapter) {
dev_err(&dssdev->dev, "can't get i2c adapter\n"); dev_err(&dssdev->dev, "can't get i2c adapter\n");
r = -ENODEV; return -ENODEV;
goto err;
} }
picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info); picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
if (!picodlp_i2c_client) { if (!picodlp_i2c_client) {
dev_err(&dssdev->dev, "can't add i2c device::" dev_err(&dssdev->dev, "can't add i2c device::"
" picodlp_i2c_client is NULL\n"); " picodlp_i2c_client is NULL\n");
r = -ENODEV; return -ENODEV;
goto err;
} }
picod->picodlp_i2c_client = picodlp_i2c_client; picod->picodlp_i2c_client = picodlp_i2c_client;
dev_set_drvdata(&dssdev->dev, picod); dev_set_drvdata(&dssdev->dev, picod);
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; return r;
err: }
kfree(picod);
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 r;
}
return 0;
} }
static void picodlp_panel_remove(struct omap_dss_device *dssdev) static void picodlp_panel_remove(struct omap_dss_device *dssdev)
......
...@@ -20,16 +20,13 @@ ...@@ -20,16 +20,13 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/backlight.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-data.h>
struct sharp_data {
struct backlight_device *bl;
};
static struct omap_video_timings sharp_ls_timings = { static struct omap_video_timings sharp_ls_timings = {
.x_res = 480, .x_res = 480,
...@@ -52,91 +49,67 @@ static struct omap_video_timings sharp_ls_timings = { ...@@ -52,91 +49,67 @@ static struct omap_video_timings sharp_ls_timings = {
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, .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); return (struct panel_sharp_ls037v7dw01_data *) dssdev->data;
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);
} }
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) static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
{ {
struct backlight_properties props; struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
struct backlight_device *bl;
struct sharp_data *sd;
int r; int r;
if (!pd)
return -EINVAL;
dssdev->panel.timings = sharp_ls_timings; dssdev->panel.timings = sharp_ls_timings;
sd = kzalloc(sizeof(*sd), GFP_KERNEL); if (gpio_is_valid(pd->mo_gpio)) {
if (!sd) r = devm_gpio_request_one(&dssdev->dev, pd->mo_gpio,
return -ENOMEM; GPIOF_OUT_INIT_LOW, "lcd MO");
if (r)
return r;
}
dev_set_drvdata(&dssdev->dev, sd); 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;
}
memset(&props, 0, sizeof(struct backlight_properties)); if (gpio_is_valid(pd->ud_gpio)) {
props.max_brightness = dssdev->max_backlight_level; r = devm_gpio_request_one(&dssdev->dev, pd->ud_gpio,
props.type = BACKLIGHT_RAW; GPIOF_OUT_INIT_HIGH, "lcd UD");
if (r)
return r;
}
bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev, if (gpio_is_valid(pd->resb_gpio)) {
&sharp_ls_bl_ops, &props); r = devm_gpio_request_one(&dssdev->dev, pd->resb_gpio,
if (IS_ERR(bl)) { GPIOF_OUT_INIT_LOW, "lcd RESB");
r = PTR_ERR(bl); if (r)
kfree(sd);
return r; return r;
} }
sd->bl = bl;
bl->props.fb_blank = FB_BLANK_UNBLANK; if (gpio_is_valid(pd->ini_gpio)) {
bl->props.power = FB_BLANK_UNBLANK; r = devm_gpio_request_one(&dssdev->dev, pd->ini_gpio,
bl->props.brightness = dssdev->max_backlight_level; GPIOF_OUT_INIT_LOW, "lcd INI");
r = sharp_ls_bl_update_status(bl); if (r)
if (r < 0) return r;
dev_err(&dssdev->dev, "failed to set lcd brightness\n"); }
return 0; return 0;
} }
static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev) 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) static int sharp_ls_power_on(struct omap_dss_device *dssdev)
{ {
struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
int r = 0; int r = 0;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
...@@ -152,26 +125,29 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev) ...@@ -152,26 +125,29 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
/* wait couple of vsyncs until enabling the LCD */ /* wait couple of vsyncs until enabling the LCD */
msleep(50); msleep(50);
if (dssdev->platform_enable) { if (gpio_is_valid(pd->resb_gpio))
r = dssdev->platform_enable(dssdev); gpio_set_value_cansleep(pd->resb_gpio, 1);
if (r)
goto err1; if (gpio_is_valid(pd->ini_gpio))
} gpio_set_value_cansleep(pd->ini_gpio, 1);
return 0; return 0;
err1:
omapdss_dpi_display_disable(dssdev);
err0: err0:
return r; return r;
} }
static void sharp_ls_power_off(struct omap_dss_device *dssdev) 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) if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return; return;
if (dssdev->platform_disable) if (gpio_is_valid(pd->ini_gpio))
dssdev->platform_disable(dssdev); 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 */ /* wait at least 5 vsyncs after disabling the LCD */
......
This diff is collapsed.
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <drm/drm_edid.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 = { static const struct omap_video_timings tfp410_default_timings = {
.x_res = 640, .x_res = 640,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-data.h>
#define TPO_R02_MODE(x) ((x) & 7) #define TPO_R02_MODE(x) ((x) & 7)
#define TPO_R02_MODE_800x480 7 #define TPO_R02_MODE_800x480 7
...@@ -278,9 +279,14 @@ static const struct omap_video_timings tpo_td043_timings = { ...@@ -278,9 +279,14 @@ static const struct omap_video_timings tpo_td043_timings = {
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, .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) static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
{ {
int nreset_gpio = tpo_td043->nreset_gpio;
int r; int r;
if (tpo_td043->powered_on) if (tpo_td043->powered_on)
...@@ -293,8 +299,8 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) ...@@ -293,8 +299,8 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
/* wait for panel to stabilize */ /* wait for panel to stabilize */
msleep(160); msleep(160);
if (gpio_is_valid(nreset_gpio)) if (gpio_is_valid(tpo_td043->nreset_gpio))
gpio_set_value(nreset_gpio, 1); gpio_set_value(tpo_td043->nreset_gpio, 1);
tpo_td043_write(tpo_td043->spi, 2, tpo_td043_write(tpo_td043->spi, 2,
TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING); 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) ...@@ -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) static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
{ {
int nreset_gpio = tpo_td043->nreset_gpio;
if (!tpo_td043->powered_on) if (!tpo_td043->powered_on)
return; return;
tpo_td043_write(tpo_td043->spi, 3, tpo_td043_write(tpo_td043->spi, 3,
TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM); TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
if (gpio_is_valid(nreset_gpio)) if (gpio_is_valid(tpo_td043->nreset_gpio))
gpio_set_value(nreset_gpio, 0); gpio_set_value(tpo_td043->nreset_gpio, 0);
/* wait for at least 2 vsyncs before cutting off power */ /* wait for at least 2 vsyncs before cutting off power */
msleep(50); msleep(50);
...@@ -347,12 +351,6 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev) ...@@ -347,12 +351,6 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
if (r) if (r)
goto err0; 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 * 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. * 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) ...@@ -379,9 +377,6 @@ static void tpo_td043_disable_dss(struct omap_dss_device *dssdev)
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return; return;
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
omapdss_dpi_display_disable(dssdev); omapdss_dpi_display_disable(dssdev);
if (!tpo_td043->spi_suspended) if (!tpo_td043->spi_suspended)
...@@ -407,7 +402,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev) ...@@ -407,7 +402,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
static int tpo_td043_probe(struct omap_dss_device *dssdev) static int tpo_td043_probe(struct omap_dss_device *dssdev)
{ {
struct tpo_td043_device *tpo_td043 = g_tpo_td043; 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; int ret = 0;
dev_dbg(&dssdev->dev, "probe\n"); dev_dbg(&dssdev->dev, "probe\n");
...@@ -417,6 +412,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev) ...@@ -417,6 +412,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
return -ENODEV; return -ENODEV;
} }
if (!pdata)
return -EINVAL;
tpo_td043->nreset_gpio = pdata->nreset_gpio;
dssdev->panel.timings = tpo_td043_timings; dssdev->panel.timings = tpo_td043_timings;
dssdev->ctrl.pixel_size = 24; dssdev->ctrl.pixel_size = 24;
...@@ -430,8 +430,9 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev) ...@@ -430,8 +430,9 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
goto fail_regulator; goto fail_regulator;
} }
if (gpio_is_valid(nreset_gpio)) { if (gpio_is_valid(tpo_td043->nreset_gpio)) {
ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW, ret = devm_gpio_request_one(&dssdev->dev,
tpo_td043->nreset_gpio, GPIOF_OUT_INIT_LOW,
"lcd reset"); "lcd reset");
if (ret < 0) { if (ret < 0) {
dev_err(&dssdev->dev, "couldn't request reset GPIO\n"); dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
...@@ -457,14 +458,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev) ...@@ -457,14 +458,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
static void tpo_td043_remove(struct omap_dss_device *dssdev) static void tpo_td043_remove(struct omap_dss_device *dssdev)
{ {
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
int nreset_gpio = dssdev->reset_gpio;
dev_dbg(&dssdev->dev, "remove\n"); dev_dbg(&dssdev->dev, "remove\n");
sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group); sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
regulator_put(tpo_td043->vcc_reg); 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, 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) ...@@ -527,7 +525,6 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
return -ENOMEM; return -ENOMEM;
tpo_td043->spi = spi; tpo_td043->spi = spi;
tpo_td043->nreset_gpio = dssdev->reset_gpio;
dev_set_drvdata(&spi->dev, tpo_td043); dev_set_drvdata(&spi->dev, tpo_td043);
g_tpo_td043 = 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 ...@@ -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) static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
{ {
unsigned long timeout = msecs_to_jiffies(500); unsigned long timeout = msecs_to_jiffies(500);
struct omap_dss_device *dssdev = mgr->get_device(mgr);
u32 irq; u32 irq;
int r; int r;
if (mgr->output == NULL)
return -ENODEV;
r = dispc_runtime_get(); r = dispc_runtime_get();
if (r) if (r)
return r; return r;
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) switch (mgr->output->id) {
case OMAP_DSS_OUTPUT_VENC:
irq = DISPC_IRQ_EVSYNC_ODD; irq = DISPC_IRQ_EVSYNC_ODD;
else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI) break;
case OMAP_DSS_OUTPUT_HDMI:
irq = DISPC_IRQ_EVSYNC_EVEN; irq = DISPC_IRQ_EVSYNC_EVEN;
else break;
default:
irq = dispc_mgr_get_vsync_irq(mgr->id); irq = dispc_mgr_get_vsync_irq(mgr->id);
break;
}
r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 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 *)) ...@@ -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, d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
write, &dss_debug_fops); write, &dss_debug_fops);
if (IS_ERR(d)) return PTR_RET(d);
return PTR_ERR(d);
return 0;
} }
#else /* CONFIG_OMAP2_DSS_DEBUGFS */ #else /* CONFIG_OMAP2_DSS_DEBUGFS */
static inline int dss_initialize_debugfs(void) static inline int dss_initialize_debugfs(void)
......
...@@ -69,6 +69,8 @@ struct dispc_features { ...@@ -69,6 +69,8 @@ struct dispc_features {
u8 mgr_height_start; u8 mgr_height_start;
u16 mgr_width_max; u16 mgr_width_max;
u16 mgr_height_max; u16 mgr_height_max;
unsigned long max_lcd_pclk;
unsigned long max_tv_pclk;
int (*calc_scaling) (unsigned long pclk, unsigned long lclk, int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
const struct omap_video_timings *mgr_timings, const struct omap_video_timings *mgr_timings,
u16 width, u16 height, u16 out_width, u16 out_height, u16 width, u16 height, u16 out_width, u16 out_height,
...@@ -85,6 +87,9 @@ struct dispc_features { ...@@ -85,6 +87,9 @@ struct dispc_features {
/* no DISPC_IRQ_FRAMEDONETV on this SoC */ /* no DISPC_IRQ_FRAMEDONETV on this SoC */
bool no_framedone_tv:1; 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 #define DISPC_MAX_NR_FIFOS 5
...@@ -97,6 +102,8 @@ static struct { ...@@ -97,6 +102,8 @@ static struct {
int irq; int irq;
unsigned long core_clk_rate;
u32 fifo_size[DISPC_MAX_NR_FIFOS]; u32 fifo_size[DISPC_MAX_NR_FIFOS];
/* maps which plane is using a fifo. fifo-id -> plane-id */ /* maps which plane is using a fifo. fifo-id -> plane-id */
int fifo_assignment[DISPC_MAX_NR_FIFOS]; int fifo_assignment[DISPC_MAX_NR_FIFOS];
...@@ -1584,6 +1591,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane, ...@@ -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, 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 mirroring, enum omap_color_mode color_mode)
{ {
bool row_repeat = false; bool row_repeat = false;
...@@ -1634,6 +1642,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, ...@@ -1634,6 +1642,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
if (dss_has_feature(FEAT_ROWREPEATENABLE)) if (dss_has_feature(FEAT_ROWREPEATENABLE))
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
row_repeat ? 1 : 0, 18, 18); row_repeat ? 1 : 0, 18, 18);
if (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) 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, ...@@ -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_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_zorder(plane, caps, zorder);
dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha); 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, ...@@ -2823,6 +2841,15 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
return true; 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, bool dispc_mgr_timings_ok(enum omap_channel channel,
const struct omap_video_timings *timings) const struct omap_video_timings *timings)
{ {
...@@ -2830,11 +2857,13 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, ...@@ -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); timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
if (dss_mgr_is_lcd(channel)) timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixel_clock * 1000);
timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw,
timings->hfp, timings->hbp, if (dss_mgr_is_lcd(channel)) {
timings->vsw, timings->vfp, timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
timings->hbp, timings->vsw, timings->vfp,
timings->vbp); timings->vbp);
}
return timings_ok; return timings_ok;
} }
...@@ -2951,6 +2980,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, ...@@ -2951,6 +2980,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
dispc_write_reg(DISPC_DIVISORo(channel), dispc_write_reg(DISPC_DIVISORo(channel),
FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
if (dss_has_feature(FEAT_CORE_CLK_DIV) == 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, 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) ...@@ -3056,15 +3089,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
unsigned long dispc_core_clk_rate(void) unsigned long dispc_core_clk_rate(void)
{ {
int lcd; return dispc.core_clk_rate;
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;
} }
static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
...@@ -3313,67 +3338,79 @@ static void dispc_dump_regs(struct seq_file *s) ...@@ -3313,67 +3338,79 @@ static void dispc_dump_regs(struct seq_file *s)
#undef DUMPREG #undef DUMPREG
} }
/* with fck as input clock rate, find dispc dividers that produce req_pck */ /* calculate clock rates using dividers in cinfo */
void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
struct dispc_clock_info *cinfo) struct dispc_clock_info *cinfo)
{ {
u16 pcd_min, pcd_max; if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
unsigned long best_pck; return -EINVAL;
u16 best_ld, cur_ld; if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
u16 best_pd, cur_pd; return -EINVAL;
pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); cinfo->pck = cinfo->lck / cinfo->pck_div;
best_pck = 0; return 0;
best_ld = 0; }
best_pd = 0;
for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { bool dispc_div_calc(unsigned long dispc,
unsigned long lck = fck / cur_ld; 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;
for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) { #ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
unsigned long pck = lck / cur_pd; min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
long old_delta = abs(best_pck - req_pck); #else
long new_delta = abs(pck - req_pck); min_fck_per_pck = 0;
#endif
if (best_pck == 0 || new_delta < old_delta) { pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
best_pck = pck; pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
best_ld = cur_ld;
best_pd = cur_pd;
if (pck == req_pck) lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
goto found;
}
if (pck < req_pck) pck_min = pck_min ? pck_min : 1;
break; pck_max = pck_max ? pck_max : ULONG_MAX;
}
if (lck / pcd_min < req_pck) lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
break; lckd_stop = min(dispc / pck_min, 255ul);
}
found: for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
cinfo->lck_div = best_ld; lck = dispc / lckd;
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 */ pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, pckd_stop = min(lck / pck_min, pckd_hw_max);
struct dispc_clock_info *cinfo)
{
if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
return -EINVAL;
if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
return -EINVAL;
cinfo->lck = dispc_fclk_rate / cinfo->lck_div; for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
cinfo->pck = cinfo->lck / cinfo->pck_div; pck = lck / pckd;
return 0; /*
* 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, void dispc_mgr_set_clock_div(enum omap_channel channel,
...@@ -3451,6 +3488,8 @@ static void _omap_dispc_initial_config(void) ...@@ -3451,6 +3488,8 @@ static void _omap_dispc_initial_config(void)
l = FLD_MOD(l, 1, 0, 0); l = FLD_MOD(l, 1, 0, 0);
l = FLD_MOD(l, 1, 23, 16); l = FLD_MOD(l, 1, 23, 16);
dispc_write_reg(DISPC_DIVISOR, l); dispc_write_reg(DISPC_DIVISOR, l);
dispc.core_clk_rate = dispc_fclk_rate();
} }
/* FUNCGATED */ /* FUNCGATED */
...@@ -3466,6 +3505,9 @@ static void _omap_dispc_initial_config(void) ...@@ -3466,6 +3505,9 @@ static void _omap_dispc_initial_config(void)
dispc_configure_burst_sizes(); dispc_configure_burst_sizes();
dispc_ovl_enable_zorder_planes(); 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 = { static const struct dispc_features omap24xx_dispc_feats __initconst = {
...@@ -3479,6 +3521,7 @@ 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_height_start = 26,
.mgr_width_max = 2048, .mgr_width_max = 2048,
.mgr_height_max = 2048, .mgr_height_max = 2048,
.max_lcd_pclk = 66500000,
.calc_scaling = dispc_ovl_calc_scaling_24xx, .calc_scaling = dispc_ovl_calc_scaling_24xx,
.calc_core_clk = calc_core_clk_24xx, .calc_core_clk = calc_core_clk_24xx,
.num_fifos = 3, .num_fifos = 3,
...@@ -3496,6 +3539,8 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { ...@@ -3496,6 +3539,8 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
.mgr_height_start = 26, .mgr_height_start = 26,
.mgr_width_max = 2048, .mgr_width_max = 2048,
.mgr_height_max = 2048, .mgr_height_max = 2048,
.max_lcd_pclk = 173000000,
.max_tv_pclk = 59000000,
.calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_scaling = dispc_ovl_calc_scaling_34xx,
.calc_core_clk = calc_core_clk_34xx, .calc_core_clk = calc_core_clk_34xx,
.num_fifos = 3, .num_fifos = 3,
...@@ -3513,6 +3558,8 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { ...@@ -3513,6 +3558,8 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
.mgr_height_start = 26, .mgr_height_start = 26,
.mgr_width_max = 2048, .mgr_width_max = 2048,
.mgr_height_max = 2048, .mgr_height_max = 2048,
.max_lcd_pclk = 173000000,
.max_tv_pclk = 59000000,
.calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_scaling = dispc_ovl_calc_scaling_34xx,
.calc_core_clk = calc_core_clk_34xx, .calc_core_clk = calc_core_clk_34xx,
.num_fifos = 3, .num_fifos = 3,
...@@ -3530,6 +3577,8 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = { ...@@ -3530,6 +3577,8 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
.mgr_height_start = 26, .mgr_height_start = 26,
.mgr_width_max = 2048, .mgr_width_max = 2048,
.mgr_height_max = 2048, .mgr_height_max = 2048,
.max_lcd_pclk = 170000000,
.max_tv_pclk = 185625000,
.calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_scaling = dispc_ovl_calc_scaling_44xx,
.calc_core_clk = calc_core_clk_44xx, .calc_core_clk = calc_core_clk_44xx,
.num_fifos = 5, .num_fifos = 5,
...@@ -3547,10 +3596,13 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = { ...@@ -3547,10 +3596,13 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = {
.mgr_height_start = 27, .mgr_height_start = 27,
.mgr_width_max = 4096, .mgr_width_max = 4096,
.mgr_height_max = 4096, .mgr_height_max = 4096,
.max_lcd_pclk = 170000000,
.max_tv_pclk = 186000000,
.calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_scaling = dispc_ovl_calc_scaling_44xx,
.calc_core_clk = calc_core_clk_44xx, .calc_core_clk = calc_core_clk_44xx,
.num_fifos = 5, .num_fifos = 5,
.gfx_fifo_workaround = true, .gfx_fifo_workaround = true,
.mstandby_workaround = true,
}; };
static int __init dispc_init_features(struct platform_device *pdev) static int __init dispc_init_features(struct platform_device *pdev)
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define DISPC_GLOBAL_BUFFER 0x0800 #define DISPC_GLOBAL_BUFFER 0x0800
#define DISPC_CONTROL3 0x0848 #define DISPC_CONTROL3 0x0848
#define DISPC_CONFIG3 0x084C #define DISPC_CONFIG3 0x084C
#define DISPC_MSTANDBY_CTRL 0x0858
/* DISPC overlay registers */ /* DISPC overlay registers */
#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ #define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
......
This diff is collapsed.
This diff is collapsed.
...@@ -473,6 +473,47 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo) ...@@ -473,6 +473,47 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
return 0; 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) int dss_set_clock_div(struct dss_clock_info *cinfo)
{ {
if (dss.dpll4_m4_ck) { if (dss.dpll4_m4_ck) {
...@@ -482,7 +523,8 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) ...@@ -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)); prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
DSSDBG("dpll4_m4 = %ld\n", prate); 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) if (r)
return r; return r;
} else { } else {
...@@ -492,7 +534,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) ...@@ -492,7 +534,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
dss.dss_clk_rate = clk_get_rate(dss.dss_clk); 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); DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
...@@ -542,121 +586,6 @@ static int dss_setup_default_clock(void) ...@@ -542,121 +586,6 @@ static int dss_setup_default_clock(void)
return 0; 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) void dss_set_venc_output(enum omap_dss_venc_type type)
{ {
int l = 0; int l = 0;
...@@ -767,13 +696,11 @@ int dss_dpi_select_source(enum omap_channel channel) ...@@ -767,13 +696,11 @@ int dss_dpi_select_source(enum omap_channel channel)
static int dss_get_clocks(void) static int dss_get_clocks(void)
{ {
struct clk *clk; struct clk *clk;
int r;
clk = clk_get(&dss.pdev->dev, "fck"); clk = devm_clk_get(&dss.pdev->dev, "fck");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
DSSERR("can't get clock fck\n"); DSSERR("can't get clock fck\n");
r = PTR_ERR(clk); return PTR_ERR(clk);
goto err;
} }
dss.dss_clk = clk; dss.dss_clk = clk;
...@@ -782,8 +709,7 @@ static int dss_get_clocks(void) ...@@ -782,8 +709,7 @@ static int dss_get_clocks(void)
clk = clk_get(NULL, dss.feat->clk_name); clk = clk_get(NULL, dss.feat->clk_name);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
DSSERR("Failed to get %s\n", dss.feat->clk_name); DSSERR("Failed to get %s\n", dss.feat->clk_name);
r = PTR_ERR(clk); return PTR_ERR(clk);
goto err;
} }
} else { } else {
clk = NULL; clk = NULL;
...@@ -792,21 +718,12 @@ static int dss_get_clocks(void) ...@@ -792,21 +718,12 @@ static int dss_get_clocks(void)
dss.dpll4_m4_ck = clk; dss.dpll4_m4_ck = clk;
return 0; 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) static void dss_put_clocks(void)
{ {
if (dss.dpll4_m4_ck) if (dss.dpll4_m4_ck)
clk_put(dss.dpll4_m4_ck); clk_put(dss.dpll4_m4_ck);
clk_put(dss.dss_clk);
} }
static int dss_runtime_get(void) static int dss_runtime_get(void)
......
...@@ -268,8 +268,9 @@ void dss_set_dac_pwrdn_bgz(bool enable); ...@@ -268,8 +268,9 @@ void dss_set_dac_pwrdn_bgz(bool enable);
unsigned long dss_get_dpll4_rate(void); unsigned long dss_get_dpll4_rate(void);
int dss_calc_clock_rates(struct dss_clock_info *cinfo); int dss_calc_clock_rates(struct dss_clock_info *cinfo);
int dss_set_clock_div(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 */ /* SDI */
int sdi_init_platform_driver(void) __init; int sdi_init_platform_driver(void) __init;
...@@ -292,12 +293,21 @@ void dsi_dump_clocks(struct seq_file *s); ...@@ -292,12 +293,21 @@ void dsi_dump_clocks(struct seq_file *s);
void dsi_irq_handler(void); void dsi_irq_handler(void);
u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); 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); unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
int dsi_pll_set_clock_div(struct platform_device *dsidev, int dsi_pll_set_clock_div(struct platform_device *dsidev,
struct dsi_clock_info *cinfo); 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, int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
bool enable_hsdiv); bool enable_hsdiv);
void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); 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, ...@@ -328,14 +338,6 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
WARN("%s: DSI not compiled in\n", __func__); WARN("%s: DSI not compiled in\n", __func__);
return -ENODEV; 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, static inline int dsi_pll_init(struct platform_device *dsidev,
bool enable_hsclk, bool enable_hsdiv) bool enable_hsclk, bool enable_hsdiv)
{ {
...@@ -376,11 +378,15 @@ void dispc_enable_fifomerge(bool enable); ...@@ -376,11 +378,15 @@ void dispc_enable_fifomerge(bool enable);
void dispc_enable_gamma_table(bool enable); void dispc_enable_gamma_table(bool enable);
void dispc_set_loadmode(enum omap_dss_load_mode mode); 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, bool dispc_mgr_timings_ok(enum omap_channel channel,
const struct omap_video_timings *timings); const struct omap_video_timings *timings);
unsigned long dispc_fclk_rate(void); 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, int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
struct dispc_clock_info *cinfo); struct dispc_clock_info *cinfo);
......
...@@ -414,7 +414,7 @@ static const char * const omap5_dss_clk_source_names[] = { ...@@ -414,7 +414,7 @@ static const char * const omap5_dss_clk_source_names[] = {
}; };
static const struct dss_param_range omap2_dss_param_range[] = { 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_DSS_PCD] = { 2, 255 },
[FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
[FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
...@@ -459,15 +459,15 @@ static const struct dss_param_range omap4_dss_param_range[] = { ...@@ -459,15 +459,15 @@ static const struct dss_param_range omap4_dss_param_range[] = {
}; };
static const struct dss_param_range omap5_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_DSS_PCD] = { 1, 255 },
[FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
[FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 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_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_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
}; };
......
...@@ -472,17 +472,12 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, ...@@ -472,17 +472,12 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
* Input clock is predivided by N + 1 * Input clock is predivided by N + 1
* out put of which is reference clk * out put of which is reference clk
*/ */
if (dssdev->clocks.hdmi.regn == 0)
pi->regn = HDMI_DEFAULT_REGN; pi->regn = HDMI_DEFAULT_REGN;
else
pi->regn = dssdev->clocks.hdmi.regn;
refclk = clkin / pi->regn; refclk = clkin / pi->regn;
if (dssdev->clocks.hdmi.regm2 == 0)
pi->regm2 = HDMI_DEFAULT_REGM2; pi->regm2 = HDMI_DEFAULT_REGM2;
else
pi->regm2 = dssdev->clocks.hdmi.regm2;
/* /*
* multiplier is pixel_clk/ref_clk * multiplier is pixel_clk/ref_clk
...@@ -804,7 +799,7 @@ static int hdmi_get_clocks(struct platform_device *pdev) ...@@ -804,7 +799,7 @@ static int hdmi_get_clocks(struct platform_device *pdev)
{ {
struct clk *clk; struct clk *clk;
clk = clk_get(&pdev->dev, "sys_clk"); clk = devm_clk_get(&pdev->dev, "sys_clk");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
DSSERR("can't get sys_clk\n"); DSSERR("can't get sys_clk\n");
return PTR_ERR(clk); return PTR_ERR(clk);
...@@ -815,12 +810,6 @@ static int hdmi_get_clocks(struct platform_device *pdev) ...@@ -815,12 +810,6 @@ static int hdmi_get_clocks(struct platform_device *pdev)
return 0; return 0;
} }
static void hdmi_put_clocks(void)
{
if (hdmi.sys_clk)
clk_put(hdmi.sys_clk);
}
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) 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) ...@@ -1017,8 +1006,6 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
hdmi.ls_oe_gpio = priv->ls_oe_gpio; hdmi.ls_oe_gpio = priv->ls_oe_gpio;
hdmi.hpd_gpio = priv->hpd_gpio; hdmi.hpd_gpio = priv->hpd_gpio;
dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
r = hdmi_init_display(dssdev); r = hdmi_init_display(dssdev);
if (r) { if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, 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) ...@@ -1051,6 +1038,8 @@ static void __init hdmi_init_output(struct platform_device *pdev)
out->pdev = pdev; out->pdev = pdev;
out->id = OMAP_DSS_OUTPUT_HDMI; out->id = OMAP_DSS_OUTPUT_HDMI;
out->type = OMAP_DISPLAY_TYPE_HDMI; out->type = OMAP_DISPLAY_TYPE_HDMI;
out->name = "hdmi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
dss_register_output(out); dss_register_output(out);
} }
...@@ -1097,23 +1086,19 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) ...@@ -1097,23 +1086,19 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
hdmi.ip_data.pll_offset = HDMI_PLLCTRL; hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
hdmi.ip_data.phy_offset = HDMI_PHY; hdmi.ip_data.phy_offset = HDMI_PHY;
hdmi_init_output(pdev);
r = hdmi_panel_init(); r = hdmi_panel_init();
if (r) { if (r) {
DSSERR("can't init panel\n"); DSSERR("can't init panel\n");
goto err_panel_init; return r;
} }
dss_debugfs_create_file("hdmi", hdmi_dump_regs); dss_debugfs_create_file("hdmi", hdmi_dump_regs);
hdmi_init_output(pdev);
hdmi_probe_pdata(pdev); hdmi_probe_pdata(pdev);
return 0; return 0;
err_panel_init:
hdmi_put_clocks();
return r;
} }
static int __exit hdmi_remove_child(struct device *dev, void *data) 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) ...@@ -1135,8 +1120,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
hdmi_put_clocks();
return 0; return 0;
} }
......
...@@ -113,6 +113,7 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id) ...@@ -113,6 +113,7 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
return NULL; return NULL;
} }
EXPORT_SYMBOL(omap_dss_get_output);
static const struct dss_mgr_ops *dss_mgr_ops; static const struct dss_mgr_ops *dss_mgr_ops;
......
...@@ -1025,6 +1025,8 @@ static void __init rfbi_init_output(struct platform_device *pdev) ...@@ -1025,6 +1025,8 @@ static void __init rfbi_init_output(struct platform_device *pdev)
out->pdev = pdev; out->pdev = pdev;
out->id = OMAP_DSS_OUTPUT_DBI; out->id = OMAP_DSS_OUTPUT_DBI;
out->type = OMAP_DISPLAY_TYPE_DBI; out->type = OMAP_DISPLAY_TYPE_DBI;
out->name = "rfbi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
dss_register_output(out); dss_register_output(out);
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -2388,7 +2388,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev, ...@@ -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_device *dssdev = fbdev->displays[i].dssdev;
struct omap_dss_output *out = dssdev->output; 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) if (!mgr || !out)
continue; continue;
......
This diff is collapsed.
This diff is collapsed.
#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
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment