Commit 965e32b1 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-3.1-rc1' of git://gitorious.org/linux-omap-dss2/linux

* 'for-3.1-rc1' of git://gitorious.org/linux-omap-dss2/linux: (31 commits)
  OMAP: DSS2: HDMI: fix hdmi clock name
  HACK: OMAP: DSS2: clk hack for OMAP2/3
  OMAP: DSS2: DSS: Fix context save/restore
  OMAP: DSS2: DISPC: Fix context save/restore
  OMAP: DSS2: Remove ctx loss count from dss.c
  OMAP: DSS2: Remove unused code from display.c
  OMAP: DSS2: DISPC: remove finegrained clk enables/disables
  OMAP: DSS2: Remove unused opt_clock_available
  OMAP: DSS2: Use PM runtime & HWMOD support
  OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
  OMAP: DSS2: Remove core_dump_clocks
  OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable
  OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss count
  OMAP: DSS2: rewrite use of context_loss_count
  OMAP: DSS2: Remove clk optimization at dss init
  OMAP: DSS2: Fix init and unit sequence
  OMAP: DSS2: Clean up probe for DSS & DSI
  OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks
  OMAP: DSS2: Fix FIFO threshold and burst size for OMAP4
  OMAP: DSS2: DSI: sync when disabling a display
  ...
parents e10b87d2 df5d3ed2
......@@ -25,6 +25,7 @@
#include <video/omapdss.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
#include <plat/omap-pm.h>
static struct platform_device omap_display_device = {
.name = "omapdss",
......@@ -42,20 +43,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = {
},
};
/* oh_core is used for getting opt-clocks */
static struct omap_hwmod *oh_core;
static bool opt_clock_available(const char *clk_role)
{
int i;
for (i = 0; i < oh_core->opt_clks_cnt; i++) {
if (!strcmp(oh_core->opt_clks[i].role, clk_role))
return true;
}
return false;
}
struct omap_dss_hwmod_data {
const char *oh_name;
const char *dev_name;
......@@ -109,16 +96,9 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
}
/* opt_clks are always associated with dss hwmod */
oh_core = omap_hwmod_lookup("dss_core");
if (!oh_core) {
pr_err("Could not look up dss_core.\n");
return -ENODEV;
}
pdata.board_data = board_data;
pdata.board_data->get_last_off_on_transaction_id = NULL;
pdata.opt_clock_available = opt_clock_available;
pdata.board_data->get_context_loss_count =
omap_pm_get_dev_context_loss_count;
for (i = 0; i < oh_count; i++) {
oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name);
......
......@@ -504,14 +504,18 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
return 0;
r = omapdss_dsi_display_enable(dssdev);
if (r)
goto err;
if (r) {
dev_err(&dssdev->dev, "failed to enable DSI\n");
goto err1;
}
omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
r = _taal_enable_te(dssdev, true);
if (r)
goto err;
if (r) {
dev_err(&dssdev->dev, "failed to re-enable TE");
goto err2;
}
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
......@@ -521,13 +525,15 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
return 0;
err:
dev_err(&dssdev->dev, "exit ULPS failed");
r = taal_panel_reset(dssdev);
err2:
dev_err(&dssdev->dev, "failed to exit ULPS");
r = taal_panel_reset(dssdev);
if (!r) {
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
td->ulps_enabled = false;
}
err1:
taal_queue_ulps_work(dssdev);
return r;
......@@ -1241,11 +1247,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
int r;
r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
if (!r) {
if (!r)
r = taal_sleep_in(td);
/* HACK: wait a bit so that the message goes through */
msleep(10);
}
if (r) {
dev_err(&dssdev->dev,
......@@ -1317,7 +1320,10 @@ static void taal_disable(struct omap_dss_device *dssdev)
dsi_bus_lock(dssdev);
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
taal_wake_up(dssdev);
int r;
r = taal_wake_up(dssdev);
if (!r)
taal_power_off(dssdev);
}
......@@ -1897,20 +1903,6 @@ static void taal_esd_work(struct work_struct *work)
mutex_unlock(&td->lock);
}
static int taal_set_update_mode(struct omap_dss_device *dssdev,
enum omap_dss_update_mode mode)
{
if (mode != OMAP_DSS_UPDATE_MANUAL)
return -EINVAL;
return 0;
}
static enum omap_dss_update_mode taal_get_update_mode(
struct omap_dss_device *dssdev)
{
return OMAP_DSS_UPDATE_MANUAL;
}
static struct omap_dss_driver taal_driver = {
.probe = taal_probe,
.remove = __exit_p(taal_remove),
......@@ -1920,9 +1912,6 @@ static struct omap_dss_driver taal_driver = {
.suspend = taal_suspend,
.resume = taal_resume,
.set_update_mode = taal_set_update_mode,
.get_update_mode = taal_get_update_mode,
.update = taal_update,
.sync = taal_sync,
......
......@@ -117,18 +117,6 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
Max FCK is 173MHz, so this doesn't work if your PCK
is very high.
config OMAP2_DSS_SLEEP_BEFORE_RESET
bool "Sleep 50ms before DSS reset"
default y
help
For some unknown reason we may get SYNC_LOST errors from the display
subsystem at initialization time if we don't sleep before resetting
the DSS. See the source (dss.c) for more comments.
However, 50ms is quite long time to sleep, and with some
configurations the SYNC_LOST may never happen, so the sleep can
be disabled here.
config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
bool "Sleep 20ms after VENC reset"
default y
......
......@@ -183,8 +183,11 @@ static int omap_dss_probe(struct platform_device *pdev)
goto err_dss;
}
/* keep clocks enabled to prevent context saves/restores during init */
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
r = dispc_init_platform_driver();
if (r) {
DSSERR("Failed to initialize dispc platform driver\n");
goto err_dispc;
}
r = rfbi_init_platform_driver();
if (r) {
......@@ -192,12 +195,6 @@ static int omap_dss_probe(struct platform_device *pdev)
goto err_rfbi;
}
r = dispc_init_platform_driver();
if (r) {
DSSERR("Failed to initialize dispc platform driver\n");
goto err_dispc;
}
r = venc_init_platform_driver();
if (r) {
DSSERR("Failed to initialize venc platform driver\n");
......@@ -238,8 +235,6 @@ static int omap_dss_probe(struct platform_device *pdev)
pdata->default_device = dssdev;
}
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
return 0;
err_register:
......@@ -268,11 +263,11 @@ static int omap_dss_remove(struct platform_device *pdev)
dss_uninitialize_debugfs();
hdmi_uninit_platform_driver();
dsi_uninit_platform_driver();
venc_uninit_platform_driver();
dispc_uninit_platform_driver();
rfbi_uninit_platform_driver();
dsi_uninit_platform_driver();
hdmi_uninit_platform_driver();
dispc_uninit_platform_driver();
dss_uninit_platform_driver();
dss_uninit_overlays(pdev);
......
This diff is collapsed.
......@@ -29,6 +29,7 @@
#include <video/omapdss.h>
#include "dss.h"
#include "dss_features.h"
static ssize_t display_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
......@@ -65,48 +66,6 @@ static ssize_t display_enabled_store(struct device *dev,
return size;
}
static ssize_t display_upd_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
if (dssdev->driver->get_update_mode)
mode = dssdev->driver->get_update_mode(dssdev);
return snprintf(buf, PAGE_SIZE, "%d\n", mode);
}
static ssize_t display_upd_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
int val, r;
enum omap_dss_update_mode mode;
if (!dssdev->driver->set_update_mode)
return -EINVAL;
r = kstrtoint(buf, 0, &val);
if (r)
return r;
switch (val) {
case OMAP_DSS_UPDATE_DISABLED:
case OMAP_DSS_UPDATE_AUTO:
case OMAP_DSS_UPDATE_MANUAL:
mode = (enum omap_dss_update_mode)val;
break;
default:
return -EINVAL;
}
r = dssdev->driver->set_update_mode(dssdev, mode);
if (r)
return r;
return size;
}
static ssize_t display_tear_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
......@@ -294,8 +253,6 @@ static ssize_t display_wss_store(struct device *dev,
static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
display_enabled_show, display_enabled_store);
static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
display_upd_mode_show, display_upd_mode_store);
static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
display_tear_show, display_tear_store);
static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
......@@ -309,7 +266,6 @@ static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
static struct device_attribute *display_sysfs_attrs[] = {
&dev_attr_enabled,
&dev_attr_update_mode,
&dev_attr_tear_elim,
&dev_attr_timings,
&dev_attr_rotate,
......@@ -327,16 +283,13 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
EXPORT_SYMBOL(omapdss_default_get_resolution);
void default_get_overlay_fifo_thresholds(enum omap_plane plane,
u32 fifo_size, enum omap_burst_size *burst_size,
u32 fifo_size, u32 burst_size,
u32 *fifo_low, u32 *fifo_high)
{
unsigned burst_size_bytes;
*burst_size = OMAP_DSS_BURST_16x32;
burst_size_bytes = 16 * 32 / 8;
unsigned buf_unit = dss_feat_get_buffer_size_unit();
*fifo_high = fifo_size - 1;
*fifo_low = fifo_size - burst_size_bytes;
*fifo_high = fifo_size - buf_unit;
*fifo_low = fifo_size - burst_size;
}
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
......
......@@ -23,7 +23,6 @@
#define DSS_SUBSYS_NAME "DPI"
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/errno.h>
......@@ -130,8 +129,6 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
bool is_tft;
int r = 0;
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dssdev->panel.acbi, dssdev->panel.acb);
......@@ -144,7 +141,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
&fck, &lck_div, &pck_div);
if (r)
goto err0;
return r;
pck = fck / lck_div / pck_div / 1000;
......@@ -158,12 +155,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
dispc_set_lcd_timings(dssdev->manager->id, t);
err0:
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
return r;
return 0;
}
static int dpi_basic_init(struct omap_dss_device *dssdev)
static void dpi_basic_init(struct omap_dss_device *dssdev)
{
bool is_tft;
......@@ -175,8 +170,6 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
dispc_set_tft_data_lines(dssdev->manager->id,
dssdev->phy.dpi.data_lines);
return 0;
}
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
......@@ -186,31 +179,38 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
goto err0;
goto err_start_dev;
}
if (cpu_is_omap34xx()) {
r = regulator_enable(dpi.vdds_dsi_reg);
if (r)
goto err1;
goto err_reg_enable;
}
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
r = dss_runtime_get();
if (r)
goto err_get_dss;
r = dpi_basic_init(dssdev);
r = dispc_runtime_get();
if (r)
goto err2;
goto err_get_dispc;
dpi_basic_init(dssdev);
if (dpi_use_dsi_pll(dssdev)) {
dss_clk_enable(DSS_CLK_SYSCK);
r = dsi_runtime_get(dpi.dsidev);
if (r)
goto err_get_dsi;
r = dsi_pll_init(dpi.dsidev, 0, 1);
if (r)
goto err3;
goto err_dsi_pll_init;
}
r = dpi_set_mode(dssdev);
if (r)
goto err4;
goto err_set_mode;
mdelay(2);
......@@ -218,19 +218,22 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
return 0;
err4:
err_set_mode:
if (dpi_use_dsi_pll(dssdev))
dsi_pll_uninit(dpi.dsidev, true);
err3:
err_dsi_pll_init:
if (dpi_use_dsi_pll(dssdev))
dss_clk_disable(DSS_CLK_SYSCK);
err2:
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
dsi_runtime_put(dpi.dsidev);
err_get_dsi:
dispc_runtime_put();
err_get_dispc:
dss_runtime_put();
err_get_dss:
if (cpu_is_omap34xx())
regulator_disable(dpi.vdds_dsi_reg);
err1:
err_reg_enable:
omap_dss_stop_device(dssdev);
err0:
err_start_dev:
return r;
}
EXPORT_SYMBOL(omapdss_dpi_display_enable);
......@@ -242,10 +245,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
if (dpi_use_dsi_pll(dssdev)) {
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dsi_pll_uninit(dpi.dsidev, true);
dss_clk_disable(DSS_CLK_SYSCK);
dsi_runtime_put(dpi.dsidev);
}
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
dispc_runtime_put();
dss_runtime_put();
if (cpu_is_omap34xx())
regulator_disable(dpi.vdds_dsi_reg);
......@@ -257,11 +261,26 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
void dpi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
int r;
DSSDBG("dpi_set_timings\n");
dssdev->panel.timings = *timings;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
r = dss_runtime_get();
if (r)
return;
r = dispc_runtime_get();
if (r) {
dss_runtime_put();
return;
}
dpi_set_mode(dssdev);
dispc_go(dssdev->manager->id);
dispc_runtime_put();
dss_runtime_put();
}
}
EXPORT_SYMBOL(dpi_set_timings);
......
This diff is collapsed.
This diff is collapsed.
......@@ -97,26 +97,12 @@ extern unsigned int dss_debug;
#define FLD_MOD(orig, val, start, end) \
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
enum omap_burst_size {
OMAP_DSS_BURST_4x32 = 0,
OMAP_DSS_BURST_8x32 = 1,
OMAP_DSS_BURST_16x32 = 2,
};
enum omap_parallel_interface_mode {
OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
OMAP_DSS_PARALLELMODE_DSI,
};
enum dss_clock {
DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */
DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */
DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */
DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */
DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/
};
enum dss_hdmi_venc_clk_source_select {
DSS_VENC_TV_CLK = 0,
DSS_HDMI_M_PCLK = 1,
......@@ -194,7 +180,7 @@ void dss_uninit_device(struct platform_device *pdev,
bool dss_use_replication(struct omap_dss_device *dssdev,
enum omap_color_mode mode);
void default_get_overlay_fifo_thresholds(enum omap_plane plane,
u32 fifo_size, enum omap_burst_size *burst_size,
u32 fifo_size, u32 burst_size,
u32 *fifo_low, u32 *fifo_high);
/* manager */
......@@ -220,13 +206,12 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
int dss_init_platform_driver(void);
void dss_uninit_platform_driver(void);
int dss_runtime_get(void);
void dss_runtime_put(void);
struct clk *dss_get_ick(void);
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
void dss_save_context(void);
void dss_restore_context(void);
void dss_clk_enable(enum dss_clock clks);
void dss_clk_disable(enum dss_clock clks);
unsigned long dss_clk_get_rate(enum dss_clock clk);
int dss_need_ctx_restore(void);
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s);
......@@ -283,15 +268,15 @@ struct file_operations;
int dsi_init_platform_driver(void);
void dsi_uninit_platform_driver(void);
int dsi_runtime_get(struct platform_device *dsidev);
void dsi_runtime_put(struct platform_device *dsidev);
void dsi_dump_clocks(struct seq_file *s);
void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
const struct file_operations *debug_fops);
void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
const struct file_operations *debug_fops);
void dsi_save_context(void);
void dsi_restore_context(void);
int dsi_init_display(struct omap_dss_device *display);
void dsi_irq_handler(void);
unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
......@@ -304,7 +289,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
bool enable_hsdiv);
void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
u32 fifo_size, enum omap_burst_size *burst_size,
u32 fifo_size, u32 burst_size,
u32 *fifo_low, u32 *fifo_high);
void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
......@@ -317,6 +302,13 @@ static inline int dsi_init_platform_driver(void)
static inline void dsi_uninit_platform_driver(void)
{
}
static inline int dsi_runtime_get(struct platform_device *dsidev)
{
return 0;
}
static inline void dsi_runtime_put(struct platform_device *dsidev)
{
}
static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
{
WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
......@@ -384,8 +376,8 @@ void dispc_dump_regs(struct seq_file *s);
void dispc_irq_handler(void);
void dispc_fake_vsync_irq(void);
void dispc_save_context(void);
void dispc_restore_context(void);
int dispc_runtime_get(void);
void dispc_runtime_put(void);
void dispc_enable_sidle(void);
void dispc_disable_sidle(void);
......@@ -398,10 +390,12 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
void dispc_set_digit_size(u16 width, u16 height);
u32 dispc_get_plane_fifo_size(enum omap_plane plane);
void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
void dispc_enable_fifomerge(bool enable);
void dispc_set_burst_size(enum omap_plane plane,
enum omap_burst_size burst_size);
u32 dispc_get_burst_size(enum omap_plane plane);
void dispc_enable_cpr(enum omap_channel channel, bool enable);
void dispc_set_cpr_coef(enum omap_channel channel,
struct omap_dss_cpr_coefs *coefs);
void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
......
......@@ -49,6 +49,9 @@ struct omap_dss_features {
const enum omap_color_mode *supported_color_modes;
const char * const *clksrc_names;
const struct dss_param_range *dss_params;
const u32 buffer_size_unit;
const u32 burst_size_unit;
};
/* This struct is assigned to one of the below during initialization */
......@@ -274,6 +277,8 @@ static const struct omap_dss_features omap2_dss_features = {
.supported_color_modes = omap2_dss_supported_color_modes,
.clksrc_names = omap2_dss_clk_source_names,
.dss_params = omap2_dss_param_range,
.buffer_size_unit = 1,
.burst_size_unit = 8,
};
/* OMAP3 DSS Features */
......@@ -286,7 +291,9 @@ static const struct omap_dss_features omap3430_dss_features = {
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
FEAT_FIR_COEF_V,
.num_mgrs = 2,
.num_ovls = 3,
......@@ -294,6 +301,8 @@ static const struct omap_dss_features omap3430_dss_features = {
.supported_color_modes = omap3_dss_supported_color_modes,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.buffer_size_unit = 1,
.burst_size_unit = 8,
};
static const struct omap_dss_features omap3630_dss_features = {
......@@ -306,7 +315,8 @@ static const struct omap_dss_features omap3630_dss_features = {
FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
FEAT_DSI_PLL_FREQSEL,
FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
FEAT_FIR_COEF_V,
.num_mgrs = 2,
.num_ovls = 3,
......@@ -314,6 +324,8 @@ static const struct omap_dss_features omap3630_dss_features = {
.supported_color_modes = omap3_dss_supported_color_modes,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.buffer_size_unit = 1,
.burst_size_unit = 8,
};
/* OMAP4 DSS Features */
......@@ -327,7 +339,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
.num_mgrs = 3,
.num_ovls = 3,
......@@ -335,6 +348,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
.supported_color_modes = omap4_dss_supported_color_modes,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.buffer_size_unit = 16,
.burst_size_unit = 16,
};
/* For all the other OMAP4 versions */
......@@ -348,7 +363,8 @@ static const struct omap_dss_features omap4_dss_features = {
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
FEAT_PRELOAD | FEAT_FIR_COEF_V,
.num_mgrs = 3,
.num_ovls = 3,
......@@ -356,6 +372,8 @@ static const struct omap_dss_features omap4_dss_features = {
.supported_color_modes = omap4_dss_supported_color_modes,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.buffer_size_unit = 16,
.burst_size_unit = 16,
};
/* Functions returning values related to a DSS feature */
......@@ -401,6 +419,16 @@ const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
return omap_current_dss_features->clksrc_names[id];
}
u32 dss_feat_get_buffer_size_unit(void)
{
return omap_current_dss_features->buffer_size_unit;
}
u32 dss_feat_get_burst_size_unit(void)
{
return omap_current_dss_features->burst_size_unit;
}
/* DSS has_feature check */
bool dss_has_feature(enum dss_feat_id id)
{
......
......@@ -51,6 +51,10 @@ enum dss_feat_id {
FEAT_HDMI_CTS_SWMODE = 1 << 19,
FEAT_HANDLE_UV_SEPARATE = 1 << 20,
FEAT_ATTR2 = 1 << 21,
FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22,
FEAT_CPR = 1 << 23,
FEAT_PRELOAD = 1 << 24,
FEAT_FIR_COEF_V = 1 << 25,
};
/* DSS register field id */
......@@ -90,6 +94,9 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode);
const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
u32 dss_feat_get_burst_size_unit(void); /* in bytes */
bool dss_has_feature(enum dss_feat_id id);
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
void dss_features_init(void);
......
......@@ -29,6 +29,9 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <video/omapdss.h>
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
......@@ -51,6 +54,9 @@ static struct {
u8 edid_set;
bool custom_set;
struct hdmi_config cfg;
struct clk *sys_clk;
struct clk *hdmi_clk;
} hdmi;
/*
......@@ -162,6 +168,27 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
return val;
}
static int hdmi_runtime_get(void)
{
int r;
DSSDBG("hdmi_runtime_get\n");
r = pm_runtime_get_sync(&hdmi.pdev->dev);
WARN_ON(r < 0);
return r < 0 ? r : 0;
}
static void hdmi_runtime_put(void)
{
int r;
DSSDBG("hdmi_runtime_put\n");
r = pm_runtime_put(&hdmi.pdev->dev);
WARN_ON(r < 0);
}
int hdmi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("init_display\n");
......@@ -311,30 +338,11 @@ static int hdmi_phy_init(void)
return 0;
}
static int hdmi_wait_softreset(void)
{
/* reset W1 */
REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
/* wait till SOFTRESET == 0 */
if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
DSSERR("sysconfig reset failed\n");
return -ETIMEDOUT;
}
return 0;
}
static int hdmi_pll_program(struct hdmi_pll_info *fmt)
{
u16 r = 0;
enum hdmi_clk_refsel refsel;
/* wait for wrapper reset */
r = hdmi_wait_softreset();
if (r)
return r;
r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
if (r)
return r;
......@@ -1064,7 +1072,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
unsigned long clkin, refclk;
u32 mf;
clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
clkin = clk_get_rate(hdmi.sys_clk) / 10000;
/*
* Input clock is predivided by N + 1
* out put of which is reference clk
......@@ -1098,16 +1106,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
}
static void hdmi_enable_clocks(int enable)
{
if (enable)
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
else
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
}
static int hdmi_power_on(struct omap_dss_device *dssdev)
{
int r, code = 0;
......@@ -1115,7 +1113,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
struct omap_video_timings *p;
unsigned long phy;
hdmi_enable_clocks(1);
r = hdmi_runtime_get();
if (r)
return r;
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
......@@ -1180,7 +1180,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
return 0;
err:
hdmi_enable_clocks(0);
hdmi_runtime_put();
return -EIO;
}
......@@ -1191,7 +1191,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
hdmi_wp_video_start(0);
hdmi_phy_off();
hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
hdmi_enable_clocks(0);
hdmi_runtime_put();
hdmi.edid_set = 0;
}
......@@ -1686,14 +1686,43 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
};
#endif
static int hdmi_get_clocks(struct platform_device *pdev)
{
struct clk *clk;
clk = clk_get(&pdev->dev, "sys_clk");
if (IS_ERR(clk)) {
DSSERR("can't get sys_clk\n");
return PTR_ERR(clk);
}
hdmi.sys_clk = clk;
clk = clk_get(&pdev->dev, "dss_48mhz_clk");
if (IS_ERR(clk)) {
DSSERR("can't get hdmi_clk\n");
clk_put(hdmi.sys_clk);
return PTR_ERR(clk);
}
hdmi.hdmi_clk = clk;
return 0;
}
static void hdmi_put_clocks(void)
{
if (hdmi.sys_clk)
clk_put(hdmi.sys_clk);
if (hdmi.hdmi_clk)
clk_put(hdmi.hdmi_clk);
}
/* HDMI HW IP initialisation */
static int omapdss_hdmihw_probe(struct platform_device *pdev)
{
struct resource *hdmi_mem;
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
int ret;
#endif
int r;
hdmi.pdata = pdev->dev.platform_data;
hdmi.pdev = pdev;
......@@ -1713,17 +1742,25 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
return -ENOMEM;
}
r = hdmi_get_clocks(pdev);
if (r) {
iounmap(hdmi.base_wp);
return r;
}
pm_runtime_enable(&pdev->dev);
hdmi_panel_init();
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
/* Register ASoC codec DAI */
ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
&hdmi_codec_dai_drv, 1);
if (ret) {
if (r) {
DSSERR("can't register ASoC HDMI audio codec\n");
return ret;
return r;
}
#endif
return 0;
......@@ -1738,17 +1775,62 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
snd_soc_unregister_codec(&pdev->dev);
#endif
pm_runtime_disable(&pdev->dev);
hdmi_put_clocks();
iounmap(hdmi.base_wp);
return 0;
}
static int hdmi_runtime_suspend(struct device *dev)
{
clk_disable(hdmi.hdmi_clk);
clk_disable(hdmi.sys_clk);
dispc_runtime_put();
dss_runtime_put();
return 0;
}
static int hdmi_runtime_resume(struct device *dev)
{
int r;
r = dss_runtime_get();
if (r < 0)
goto err_get_dss;
r = dispc_runtime_get();
if (r < 0)
goto err_get_dispc;
clk_enable(hdmi.sys_clk);
clk_enable(hdmi.hdmi_clk);
return 0;
err_get_dispc:
dss_runtime_put();
err_get_dss:
return r;
}
static const struct dev_pm_ops hdmi_pm_ops = {
.runtime_suspend = hdmi_runtime_suspend,
.runtime_resume = hdmi_runtime_resume,
};
static struct platform_driver omapdss_hdmihw_driver = {
.probe = omapdss_hdmihw_probe,
.remove = omapdss_hdmihw_remove,
.driver = {
.name = "omapdss_hdmi",
.owner = THIS_MODULE,
.pm = &hdmi_pm_ops,
},
};
......
This diff is collapsed.
......@@ -84,32 +84,42 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
old_mgr = ovl->manager;
r = dispc_runtime_get();
if (r)
return r;
/* detach old manager */
if (old_mgr) {
r = ovl->unset_manager(ovl);
if (r) {
DSSERR("detach failed\n");
return r;
goto err;
}
r = old_mgr->apply(old_mgr);
if (r)
return r;
goto err;
}
if (mgr) {
r = ovl->set_manager(ovl, mgr);
if (r) {
DSSERR("Failed to attach overlay\n");
return r;
goto err;
}
r = mgr->apply(mgr);
if (r)
return r;
goto err;
}
dispc_runtime_put();
return size;
err:
dispc_runtime_put();
return r;
}
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
......@@ -238,6 +248,9 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
u8 alpha;
struct omap_overlay_info info;
if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
return -ENODEV;
r = kstrtou8(buf, 0, &alpha);
if (r)
return r;
......@@ -504,7 +517,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
ovl->manager = mgr;
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
/* XXX: When there is an overlay on a DSI manual update display, and
* the overlay is first disabled, then moved to tv, and enabled, we
* seem to get SYNC_LOST_DIGIT error.
......@@ -518,7 +530,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
* the overlay, but before moving the overlay to TV.
*/
dispc_set_channel_out(ovl->id, mgr->id);
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
return 0;
}
......@@ -719,6 +730,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
}
if (mgr) {
dispc_runtime_get();
for (i = 0; i < dss_feat_get_num_ovls(); i++) {
struct omap_overlay *ovl;
ovl = omap_dss_get_overlay(i);
......@@ -728,6 +741,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
omap_dss_set_manager(ovl, mgr);
}
}
dispc_runtime_put();
}
}
......
......@@ -33,6 +33,8 @@
#include <linux/hrtimer.h>
#include <linux/seq_file.h>
#include <linux/semaphore.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include "dss.h"
......@@ -120,12 +122,25 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
return __raw_readl(rfbi.base + idx.idx);
}
static void rfbi_enable_clocks(bool enable)
static int rfbi_runtime_get(void)
{
if (enable)
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
else
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
int r;
DSSDBG("rfbi_runtime_get\n");
r = pm_runtime_get_sync(&rfbi.pdev->dev);
WARN_ON(r < 0);
return r < 0 ? r : 0;
}
static void rfbi_runtime_put(void)
{
int r;
DSSDBG("rfbi_runtime_put\n");
r = pm_runtime_put(&rfbi.pdev->dev);
WARN_ON(r < 0);
}
void rfbi_bus_lock(void)
......@@ -805,7 +820,8 @@ void rfbi_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
if (rfbi_runtime_get())
return;
DUMPREG(RFBI_REVISION);
DUMPREG(RFBI_SYSCONFIG);
......@@ -836,7 +852,7 @@ void rfbi_dump_regs(struct seq_file *s)
DUMPREG(RFBI_VSYNC_WIDTH);
DUMPREG(RFBI_HSYNC_WIDTH);
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
rfbi_runtime_put();
#undef DUMPREG
}
......@@ -844,7 +860,9 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
{
int r;
rfbi_enable_clocks(1);
r = rfbi_runtime_get();
if (r)
return r;
r = omap_dss_start_device(dssdev);
if (r) {
......@@ -879,6 +897,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
err1:
omap_dss_stop_device(dssdev);
err0:
rfbi_runtime_put();
return r;
}
EXPORT_SYMBOL(omapdss_rfbi_display_enable);
......@@ -889,7 +908,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
DISPC_IRQ_FRAMEDONE);
omap_dss_stop_device(dssdev);
rfbi_enable_clocks(0);
rfbi_runtime_put();
}
EXPORT_SYMBOL(omapdss_rfbi_display_disable);
......@@ -904,8 +923,9 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
static int omap_rfbihw_probe(struct platform_device *pdev)
{
u32 rev;
u32 l;
struct resource *rfbi_mem;
struct clk *clk;
int r;
rfbi.pdev = pdev;
......@@ -914,46 +934,102 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
if (!rfbi_mem) {
DSSERR("can't get IORESOURCE_MEM RFBI\n");
return -EINVAL;
r = -EINVAL;
goto err_ioremap;
}
rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
if (!rfbi.base) {
DSSERR("can't ioremap RFBI\n");
return -ENOMEM;
r = -ENOMEM;
goto err_ioremap;
}
rfbi_enable_clocks(1);
pm_runtime_enable(&pdev->dev);
r = rfbi_runtime_get();
if (r)
goto err_get_rfbi;
msleep(10);
rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630())
clk = dss_get_ick();
else
clk = clk_get(&pdev->dev, "ick");
if (IS_ERR(clk)) {
DSSERR("can't get ick\n");
r = PTR_ERR(clk);
goto err_get_ick;
}
rfbi.l4_khz = clk_get_rate(clk) / 1000;
/* Enable autoidle and smart-idle */
l = rfbi_read_reg(RFBI_SYSCONFIG);
l |= (1 << 0) | (2 << 3);
rfbi_write_reg(RFBI_SYSCONFIG, l);
clk_put(clk);
rev = rfbi_read_reg(RFBI_REVISION);
dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
rfbi_enable_clocks(0);
rfbi_runtime_put();
return 0;
err_get_ick:
rfbi_runtime_put();
err_get_rfbi:
pm_runtime_disable(&pdev->dev);
iounmap(rfbi.base);
err_ioremap:
return r;
}
static int omap_rfbihw_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
iounmap(rfbi.base);
return 0;
}
static int rfbi_runtime_suspend(struct device *dev)
{
dispc_runtime_put();
dss_runtime_put();
return 0;
}
static int rfbi_runtime_resume(struct device *dev)
{
int r;
r = dss_runtime_get();
if (r < 0)
goto err_get_dss;
r = dispc_runtime_get();
if (r < 0)
goto err_get_dispc;
return 0;
err_get_dispc:
dss_runtime_put();
err_get_dss:
return r;
}
static const struct dev_pm_ops rfbi_pm_ops = {
.runtime_suspend = rfbi_runtime_suspend,
.runtime_resume = rfbi_runtime_resume,
};
static struct platform_driver omap_rfbihw_driver = {
.probe = omap_rfbihw_probe,
.remove = omap_rfbihw_remove,
.driver = {
.name = "omapdss_rfbi",
.owner = THIS_MODULE,
.pm = &rfbi_pm_ops,
},
};
......
......@@ -20,13 +20,11 @@
#define DSS_SUBSYS_NAME "SDI"
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/regulator/consumer.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
static struct {
......@@ -60,14 +58,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
goto err0;
goto err_start_dev;
}
r = regulator_enable(sdi.vdds_sdi_reg);
if (r)
goto err1;
goto err_reg_enable;
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
r = dss_runtime_get();
if (r)
goto err_get_dss;
r = dispc_runtime_get();
if (r)
goto err_get_dispc;
sdi_basic_init(dssdev);
......@@ -80,7 +84,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = dss_calc_clock_div(1, t->pixel_clock * 1000,
&dss_cinfo, &dispc_cinfo);
if (r)
goto err2;
goto err_calc_clock_div;
fck = dss_cinfo.fck;
lck_div = dispc_cinfo.lck_div;
......@@ -101,27 +105,34 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = dss_set_clock_div(&dss_cinfo);
if (r)
goto err2;
goto err_set_dss_clock_div;
r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
goto err2;
goto err_set_dispc_clock_div;
dss_sdi_init(dssdev->phy.sdi.datapairs);
r = dss_sdi_enable();
if (r)
goto err1;
goto err_sdi_enable;
mdelay(2);
dssdev->manager->enable(dssdev->manager);
return 0;
err2:
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
err_sdi_enable:
err_set_dispc_clock_div:
err_set_dss_clock_div:
err_calc_clock_div:
dispc_runtime_put();
err_get_dispc:
dss_runtime_put();
err_get_dss:
regulator_disable(sdi.vdds_sdi_reg);
err1:
err_reg_enable:
omap_dss_stop_device(dssdev);
err0:
err_start_dev:
return r;
}
EXPORT_SYMBOL(omapdss_sdi_display_enable);
......@@ -132,7 +143,8 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
dss_sdi_disable();
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
dispc_runtime_put();
dss_runtime_put();
regulator_disable(sdi.vdds_sdi_reg);
......
......@@ -33,11 +33,13 @@
#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
#include "dss_features.h"
/* Venc registers */
#define VENC_REV_ID 0x00
......@@ -292,6 +294,9 @@ static struct {
struct mutex venc_lock;
u32 wss_data;
struct regulator *vdda_dac_reg;
struct clk *tv_clk;
struct clk *tv_dac_clk;
} venc;
static inline void venc_write_reg(int idx, u32 val)
......@@ -380,14 +385,25 @@ static void venc_reset(void)
#endif
}
static void venc_enable_clocks(int enable)
static int venc_runtime_get(void)
{
if (enable)
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
DSS_CLK_VIDFCK);
else
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
DSS_CLK_VIDFCK);
int r;
DSSDBG("venc_runtime_get\n");
r = pm_runtime_get_sync(&venc.pdev->dev);
WARN_ON(r < 0);
return r < 0 ? r : 0;
}
static void venc_runtime_put(void)
{
int r;
DSSDBG("venc_runtime_put\n");
r = pm_runtime_put(&venc.pdev->dev);
WARN_ON(r < 0);
}
static const struct venc_config *venc_timings_to_config(
......@@ -406,8 +422,6 @@ static void venc_power_on(struct omap_dss_device *dssdev)
{
u32 l;
venc_enable_clocks(1);
venc_reset();
venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
......@@ -448,8 +462,6 @@ static void venc_power_off(struct omap_dss_device *dssdev)
dssdev->platform_disable(dssdev);
regulator_disable(venc.vdda_dac_reg);
venc_enable_clocks(0);
}
......@@ -487,6 +499,10 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
goto err1;
}
r = venc_runtime_get();
if (r)
goto err1;
venc_power_on(dssdev);
venc.wss_data = 0;
......@@ -520,6 +536,8 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
venc_power_off(dssdev);
venc_runtime_put();
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
omap_dss_stop_device(dssdev);
......@@ -538,20 +556,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev)
return venc_panel_enable(dssdev);
}
static enum omap_dss_update_mode venc_get_update_mode(
struct omap_dss_device *dssdev)
{
return OMAP_DSS_UPDATE_AUTO;
}
static int venc_set_update_mode(struct omap_dss_device *dssdev,
enum omap_dss_update_mode mode)
{
if (mode != OMAP_DSS_UPDATE_AUTO)
return -EINVAL;
return 0;
}
static void venc_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
......@@ -598,6 +602,7 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
{
const struct venc_config *config;
int r;
DSSDBG("venc_set_wss\n");
......@@ -608,16 +613,19 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
/* Invert due to VENC_L21_WC_CTL:INV=1 */
venc.wss_data = (wss ^ 0xfffff) << 8;
venc_enable_clocks(1);
r = venc_runtime_get();
if (r)
goto err;
venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
venc.wss_data);
venc_enable_clocks(0);
venc_runtime_put();
err:
mutex_unlock(&venc.venc_lock);
return 0;
return r;
}
static struct omap_dss_driver venc_driver = {
......@@ -632,9 +640,6 @@ static struct omap_dss_driver venc_driver = {
.get_resolution = omapdss_default_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
.set_update_mode = venc_set_update_mode,
.get_update_mode = venc_get_update_mode,
.get_timings = venc_get_timings,
.set_timings = venc_set_timings,
.check_timings = venc_check_timings,
......@@ -673,7 +678,8 @@ void venc_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
venc_enable_clocks(1);
if (venc_runtime_get())
return;
DUMPREG(VENC_F_CONTROL);
DUMPREG(VENC_VIDOUT_CTRL);
......@@ -717,16 +723,56 @@ void venc_dump_regs(struct seq_file *s)
DUMPREG(VENC_OUTPUT_CONTROL);
DUMPREG(VENC_OUTPUT_TEST);
venc_enable_clocks(0);
venc_runtime_put();
#undef DUMPREG
}
static int venc_get_clocks(struct platform_device *pdev)
{
struct clk *clk;
clk = clk_get(&pdev->dev, "fck");
if (IS_ERR(clk)) {
DSSERR("can't get fck\n");
return PTR_ERR(clk);
}
venc.tv_clk = clk;
if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
if (cpu_is_omap34xx() || cpu_is_omap3630())
clk = clk_get(&pdev->dev, "dss_96m_fck");
else
clk = clk_get(&pdev->dev, "tv_dac_clk");
if (IS_ERR(clk)) {
DSSERR("can't get tv_dac_clk\n");
clk_put(venc.tv_clk);
return PTR_ERR(clk);
}
} else {
clk = NULL;
}
venc.tv_dac_clk = clk;
return 0;
}
static void venc_put_clocks(void)
{
if (venc.tv_clk)
clk_put(venc.tv_clk);
if (venc.tv_dac_clk)
clk_put(venc.tv_dac_clk);
}
/* VENC HW IP initialisation */
static int omap_venchw_probe(struct platform_device *pdev)
{
u8 rev_id;
struct resource *venc_mem;
int r;
venc.pdev = pdev;
......@@ -737,22 +783,40 @@ static int omap_venchw_probe(struct platform_device *pdev)
venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
if (!venc_mem) {
DSSERR("can't get IORESOURCE_MEM VENC\n");
return -EINVAL;
r = -EINVAL;
goto err_ioremap;
}
venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
if (!venc.base) {
DSSERR("can't ioremap VENC\n");
return -ENOMEM;
r = -ENOMEM;
goto err_ioremap;
}
venc_enable_clocks(1);
r = venc_get_clocks(pdev);
if (r)
goto err_get_clk;
pm_runtime_enable(&pdev->dev);
r = venc_runtime_get();
if (r)
goto err_get_venc;
rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
venc_enable_clocks(0);
venc_runtime_put();
return omap_dss_register_driver(&venc_driver);
err_get_venc:
pm_runtime_disable(&pdev->dev);
venc_put_clocks();
err_get_clk:
iounmap(venc.base);
err_ioremap:
return r;
}
static int omap_venchw_remove(struct platform_device *pdev)
......@@ -763,16 +827,61 @@ static int omap_venchw_remove(struct platform_device *pdev)
}
omap_dss_unregister_driver(&venc_driver);
pm_runtime_disable(&pdev->dev);
venc_put_clocks();
iounmap(venc.base);
return 0;
}
static int venc_runtime_suspend(struct device *dev)
{
if (venc.tv_dac_clk)
clk_disable(venc.tv_dac_clk);
clk_disable(venc.tv_clk);
dispc_runtime_put();
dss_runtime_put();
return 0;
}
static int venc_runtime_resume(struct device *dev)
{
int r;
r = dss_runtime_get();
if (r < 0)
goto err_get_dss;
r = dispc_runtime_get();
if (r < 0)
goto err_get_dispc;
clk_enable(venc.tv_clk);
if (venc.tv_dac_clk)
clk_enable(venc.tv_dac_clk);
return 0;
err_get_dispc:
dss_runtime_put();
err_get_dss:
return r;
}
static const struct dev_pm_ops venc_pm_ops = {
.runtime_suspend = venc_runtime_suspend,
.runtime_resume = venc_runtime_resume,
};
static struct platform_driver omap_venchw_driver = {
.probe = omap_venchw_probe,
.remove = omap_venchw_remove,
.driver = {
.name = "omapdss_venc",
.owner = THIS_MODULE,
.pm = &venc_pm_ops,
},
};
......
......@@ -316,67 +316,67 @@ int omapfb_update_window(struct fb_info *fbi,
}
EXPORT_SYMBOL(omapfb_update_window);
static int omapfb_set_update_mode(struct fb_info *fbi,
int omapfb_set_update_mode(struct fb_info *fbi,
enum omapfb_update_mode mode)
{
struct omap_dss_device *display = fb2display(fbi);
enum omap_dss_update_mode um;
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omapfb_display_data *d;
int r;
if (!display || !display->driver->set_update_mode)
if (!display)
return -EINVAL;
switch (mode) {
case OMAPFB_UPDATE_DISABLED:
um = OMAP_DSS_UPDATE_DISABLED;
break;
if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
return -EINVAL;
case OMAPFB_AUTO_UPDATE:
um = OMAP_DSS_UPDATE_AUTO;
break;
omapfb_lock(fbdev);
case OMAPFB_MANUAL_UPDATE:
um = OMAP_DSS_UPDATE_MANUAL;
break;
d = get_display_data(fbdev, display);
default:
return -EINVAL;
if (d->update_mode == mode) {
omapfb_unlock(fbdev);
return 0;
}
r = 0;
if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
if (mode == OMAPFB_AUTO_UPDATE)
omapfb_start_auto_update(fbdev, display);
else /* MANUAL_UPDATE */
omapfb_stop_auto_update(fbdev, display);
d->update_mode = mode;
} else { /* AUTO_UPDATE */
if (mode == OMAPFB_MANUAL_UPDATE)
r = -EINVAL;
}
r = display->driver->set_update_mode(display, um);
omapfb_unlock(fbdev);
return r;
}
static int omapfb_get_update_mode(struct fb_info *fbi,
int omapfb_get_update_mode(struct fb_info *fbi,
enum omapfb_update_mode *mode)
{
struct omap_dss_device *display = fb2display(fbi);
enum omap_dss_update_mode m;
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omapfb_display_data *d;
if (!display)
return -EINVAL;
if (!display->driver->get_update_mode) {
*mode = OMAPFB_AUTO_UPDATE;
return 0;
}
omapfb_lock(fbdev);
m = display->driver->get_update_mode(display);
d = get_display_data(fbdev, display);
switch (m) {
case OMAP_DSS_UPDATE_DISABLED:
*mode = OMAPFB_UPDATE_DISABLED;
break;
case OMAP_DSS_UPDATE_AUTO:
*mode = OMAPFB_AUTO_UPDATE;
break;
case OMAP_DSS_UPDATE_MANUAL:
*mode = OMAPFB_MANUAL_UPDATE;
break;
default:
BUG();
}
*mode = d->update_mode;
omapfb_unlock(fbdev);
return 0;
}
......
This diff is collapsed.
......@@ -518,6 +518,39 @@ static ssize_t show_virt(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
}
static ssize_t show_upd_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *fbi = dev_get_drvdata(dev);
enum omapfb_update_mode mode;
int r;
r = omapfb_get_update_mode(fbi, &mode);
if (r)
return r;
return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
}
static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fbi = dev_get_drvdata(dev);
unsigned mode;
int r;
r = kstrtouint(buf, 0, &mode);
if (r)
return r;
r = omapfb_set_update_mode(fbi, mode);
if (r)
return r;
return count;
}
static struct device_attribute omapfb_attrs[] = {
__ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
store_rotate_type),
......@@ -528,6 +561,7 @@ static struct device_attribute omapfb_attrs[] = {
store_overlays_rotate),
__ATTR(phys_addr, S_IRUGO, show_phys, NULL),
__ATTR(virt_addr, S_IRUGO, show_virt, NULL),
__ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
};
int omapfb_create_sysfs(struct omapfb2_device *fbdev)
......
......@@ -73,6 +73,15 @@ struct omapfb_info {
bool mirror;
};
struct omapfb_display_data {
struct omapfb2_device *fbdev;
struct omap_dss_device *dssdev;
u8 bpp_override;
enum omapfb_update_mode update_mode;
bool auto_update_work_enabled;
struct delayed_work auto_update_work;
};
struct omapfb2_device {
struct device *dev;
struct mutex mtx;
......@@ -86,17 +95,13 @@ struct omapfb2_device {
struct omapfb2_mem_region regions[10];
unsigned num_displays;
struct omap_dss_device *displays[10];
struct omapfb_display_data displays[10];
unsigned num_overlays;
struct omap_overlay *overlays[10];
unsigned num_managers;
struct omap_overlay_manager *managers[10];
unsigned num_bpp_overrides;
struct {
struct omap_dss_device *dssdev;
u8 bpp;
} bpp_overrides[10];
struct workqueue_struct *auto_update_wq;
};
struct omapfb_colormode {
......@@ -128,6 +133,13 @@ int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
u16 posx, u16 posy, u16 outw, u16 outh);
void omapfb_start_auto_update(struct omapfb2_device *fbdev,
struct omap_dss_device *display);
void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
struct omap_dss_device *display);
int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
/* find the display connected to this fb, if any */
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
{
......@@ -143,6 +155,19 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
return NULL;
}
static inline struct omapfb_display_data *get_display_data(
struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
{
int i;
for (i = 0; i < fbdev->num_displays; ++i)
if (fbdev->displays[i].dssdev == dssdev)
return &fbdev->displays[i];
/* This should never happen */
BUG();
}
static inline void omapfb_lock(struct omapfb2_device *fbdev)
{
mutex_lock(&fbdev->mtx);
......
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