summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/omapdrm/dss
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/core.c5
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c471
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.h5
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc_coefs.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/display.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dpi.c136
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c57
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss-of.c3
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c255
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.h45
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss_features.c46
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss_features.h1
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi.h6
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi4.c11
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi5.c11
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi_common.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi_phy.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi_pll.c78
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi_wp.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss.h871
-rw-r--r--drivers/gpu/drm/omapdrm/dss/output.c3
-rw-r--r--drivers/gpu/drm/omapdrm/dss/pll.c129
-rw-r--r--drivers/gpu/drm/omapdrm/dss/rfbi.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/sdi.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/venc.c3
-rw-r--r--drivers/gpu/drm/omapdrm/dss/video-pll.c9
26 files changed, 1753 insertions, 406 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/core.c b/drivers/gpu/drm/omapdrm/dss/core.c
index 7e4e5bebabbe..6a3ebfcd7223 100644
--- a/drivers/gpu/drm/omapdrm/dss/core.c
+++ b/drivers/gpu/drm/omapdrm/dss/core.c
@@ -35,8 +35,7 @@
#include <linux/suspend.h>
#include <linux/slab.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
@@ -196,8 +195,6 @@ static int __init omap_dss_probe(struct platform_device *pdev)
core.default_display_name = def_disp_name;
else if (pdata->default_display_name)
core.default_display_name = pdata->default_display_name;
- else if (pdata->default_device)
- core.default_display_name = pdata->default_device->name;
return 0;
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index f83608b69e68..535240fba671 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -41,8 +41,7 @@
#include <linux/of.h>
#include <linux/component.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
#include "dispc.h"
@@ -113,9 +112,14 @@ struct dispc_features {
* never both, we can just use this flag for now.
*/
bool reverse_ilace_field_order:1;
+
+ bool has_gamma_table:1;
+
+ bool has_gamma_i734_bug:1;
};
#define DISPC_MAX_NR_FIFOS 5
+#define DISPC_MAX_CHANNEL_GAMMA 4
static struct {
struct platform_device *pdev;
@@ -135,6 +139,8 @@ static struct {
bool ctx_valid;
u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
+ u32 *gamma_table[DISPC_MAX_CHANNEL_GAMMA];
+
const struct dispc_features *feat;
bool is_enabled;
@@ -178,11 +184,19 @@ struct dispc_reg_field {
u8 low;
};
+struct dispc_gamma_desc {
+ u32 len;
+ u32 bits;
+ u16 reg;
+ bool has_index;
+};
+
static const struct {
const char *name;
u32 vsync_irq;
u32 framedone_irq;
u32 sync_lost_irq;
+ struct dispc_gamma_desc gamma;
struct dispc_reg_field reg_desc[DISPC_MGR_FLD_NUM];
} mgr_desc[] = {
[OMAP_DSS_CHANNEL_LCD] = {
@@ -190,6 +204,12 @@ static const struct {
.vsync_irq = DISPC_IRQ_VSYNC,
.framedone_irq = DISPC_IRQ_FRAMEDONE,
.sync_lost_irq = DISPC_IRQ_SYNC_LOST,
+ .gamma = {
+ .len = 256,
+ .bits = 8,
+ .reg = DISPC_GAMMA_TABLE0,
+ .has_index = true,
+ },
.reg_desc = {
[DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 0, 0 },
[DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL, 3, 3 },
@@ -207,6 +227,12 @@ static const struct {
.vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
.framedone_irq = DISPC_IRQ_FRAMEDONETV,
.sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT,
+ .gamma = {
+ .len = 1024,
+ .bits = 10,
+ .reg = DISPC_GAMMA_TABLE2,
+ .has_index = false,
+ },
.reg_desc = {
[DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 },
[DISPC_MGR_FLD_STNTFT] = { },
@@ -224,6 +250,12 @@ static const struct {
.vsync_irq = DISPC_IRQ_VSYNC2,
.framedone_irq = DISPC_IRQ_FRAMEDONE2,
.sync_lost_irq = DISPC_IRQ_SYNC_LOST2,
+ .gamma = {
+ .len = 256,
+ .bits = 8,
+ .reg = DISPC_GAMMA_TABLE1,
+ .has_index = true,
+ },
.reg_desc = {
[DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL2, 0, 0 },
[DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL2, 3, 3 },
@@ -241,6 +273,12 @@ static const struct {
.vsync_irq = DISPC_IRQ_VSYNC3,
.framedone_irq = DISPC_IRQ_FRAMEDONE3,
.sync_lost_irq = DISPC_IRQ_SYNC_LOST3,
+ .gamma = {
+ .len = 256,
+ .bits = 8,
+ .reg = DISPC_GAMMA_TABLE3,
+ .has_index = true,
+ },
.reg_desc = {
[DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL3, 0, 0 },
[DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL3, 3, 3 },
@@ -1084,20 +1122,6 @@ static u32 dispc_ovl_get_burst_size(enum omap_plane plane)
return unit * 8;
}
-void dispc_enable_gamma_table(bool enable)
-{
- /*
- * This is partially implemented to support only disabling of
- * the gamma table.
- */
- if (enable) {
- DSSWARN("Gamma table enabling for TV not yet supported");
- return;
- }
-
- REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
-}
-
static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
{
if (channel == OMAP_DSS_CHANNEL_DIGIT)
@@ -3299,30 +3323,21 @@ static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
static unsigned long dispc_fclk_rate(void)
{
- struct dss_pll *pll;
- unsigned long r = 0;
+ unsigned long r;
+ enum dss_clk_source src;
+
+ src = dss_get_dispc_clk_source();
- switch (dss_get_dispc_clk_source()) {
- case OMAP_DSS_CLK_SRC_FCK:
+ if (src == DSS_CLK_SRC_FCK) {
r = dss_get_dispc_clk_rate();
- break;
- case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
- pll = dss_pll_find("dsi0");
- if (!pll)
- pll = dss_pll_find("video0");
+ } else {
+ struct dss_pll *pll;
+ unsigned clkout_idx;
- r = pll->cinfo.clkout[0];
- break;
- case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
- pll = dss_pll_find("dsi1");
- if (!pll)
- pll = dss_pll_find("video1");
+ pll = dss_pll_find_by_src(src);
+ clkout_idx = dss_pll_get_clkout_idx_for_src(src);
- r = pll->cinfo.clkout[0];
- break;
- default:
- BUG();
- return 0;
+ r = pll->cinfo.clkout[clkout_idx];
}
return r;
@@ -3330,43 +3345,31 @@ static unsigned long dispc_fclk_rate(void)
static unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
{
- struct dss_pll *pll;
int lcd;
unsigned long r;
- u32 l;
-
- if (dss_mgr_is_lcd(channel)) {
- l = dispc_read_reg(DISPC_DIVISORo(channel));
+ enum dss_clk_source src;
- lcd = FLD_GET(l, 23, 16);
+ /* for TV, LCLK rate is the FCLK rate */
+ if (!dss_mgr_is_lcd(channel))
+ return dispc_fclk_rate();
- switch (dss_get_lcd_clk_source(channel)) {
- case OMAP_DSS_CLK_SRC_FCK:
- r = dss_get_dispc_clk_rate();
- break;
- case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
- pll = dss_pll_find("dsi0");
- if (!pll)
- pll = dss_pll_find("video0");
+ src = dss_get_lcd_clk_source(channel);
- r = pll->cinfo.clkout[0];
- break;
- case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
- pll = dss_pll_find("dsi1");
- if (!pll)
- pll = dss_pll_find("video1");
+ if (src == DSS_CLK_SRC_FCK) {
+ r = dss_get_dispc_clk_rate();
+ } else {
+ struct dss_pll *pll;
+ unsigned clkout_idx;
- r = pll->cinfo.clkout[0];
- break;
- default:
- BUG();
- return 0;
- }
+ pll = dss_pll_find_by_src(src);
+ clkout_idx = dss_pll_get_clkout_idx_for_src(src);
- return r / lcd;
- } else {
- return dispc_fclk_rate();
+ r = pll->cinfo.clkout[clkout_idx];
}
+
+ lcd = REG_GET(DISPC_DIVISORo(channel), 23, 16);
+
+ return r / lcd;
}
static unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
@@ -3426,15 +3429,14 @@ static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
{
int lcd, pcd;
- enum omap_dss_clk_source lcd_clk_src;
+ enum dss_clk_source lcd_clk_src;
seq_printf(s, "- %s -\n", mgr_desc[channel].name);
lcd_clk_src = dss_get_lcd_clk_source(channel);
- seq_printf(s, "%s clk source = %s (%s)\n", mgr_desc[channel].name,
- dss_get_generic_clk_source_name(lcd_clk_src),
- dss_feat_get_clk_source_name(lcd_clk_src));
+ seq_printf(s, "%s clk source = %s\n", mgr_desc[channel].name,
+ dss_get_clk_source_name(lcd_clk_src));
dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd);
@@ -3448,16 +3450,15 @@ void dispc_dump_clocks(struct seq_file *s)
{
int lcd;
u32 l;
- enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
+ enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
if (dispc_runtime_get())
return;
seq_printf(s, "- DISPC -\n");
- seq_printf(s, "dispc fclk source = %s (%s)\n",
- dss_get_generic_clk_source_name(dispc_clk_src),
- dss_feat_get_clk_source_name(dispc_clk_src));
+ seq_printf(s, "dispc fclk source = %s\n",
+ dss_get_clk_source_name(dispc_clk_src));
seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
@@ -3814,6 +3815,139 @@ void dispc_disable_sidle(void)
REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
}
+u32 dispc_mgr_gamma_size(enum omap_channel channel)
+{
+ const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
+
+ if (!dispc.feat->has_gamma_table)
+ return 0;
+
+ return gdesc->len;
+}
+EXPORT_SYMBOL(dispc_mgr_gamma_size);
+
+static void dispc_mgr_write_gamma_table(enum omap_channel channel)
+{
+ const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
+ u32 *table = dispc.gamma_table[channel];
+ unsigned int i;
+
+ DSSDBG("%s: channel %d\n", __func__, channel);
+
+ for (i = 0; i < gdesc->len; ++i) {
+ u32 v = table[i];
+
+ if (gdesc->has_index)
+ v |= i << 24;
+ else if (i == 0)
+ v |= 1 << 31;
+
+ dispc_write_reg(gdesc->reg, v);
+ }
+}
+
+static void dispc_restore_gamma_tables(void)
+{
+ DSSDBG("%s()\n", __func__);
+
+ if (!dispc.feat->has_gamma_table)
+ return;
+
+ dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD);
+
+ dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_DIGIT);
+
+ if (dss_has_feature(FEAT_MGR_LCD2))
+ dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD2);
+
+ if (dss_has_feature(FEAT_MGR_LCD3))
+ dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD3);
+}
+
+static const struct drm_color_lut dispc_mgr_gamma_default_lut[] = {
+ { .red = 0, .green = 0, .blue = 0, },
+ { .red = U16_MAX, .green = U16_MAX, .blue = U16_MAX, },
+};
+
+void dispc_mgr_set_gamma(enum omap_channel channel,
+ const struct drm_color_lut *lut,
+ unsigned int length)
+{
+ const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
+ u32 *table = dispc.gamma_table[channel];
+ uint i;
+
+ DSSDBG("%s: channel %d, lut len %u, hw len %u\n", __func__,
+ channel, length, gdesc->len);
+
+ if (!dispc.feat->has_gamma_table)
+ return;
+
+ if (lut == NULL || length < 2) {
+ lut = dispc_mgr_gamma_default_lut;
+ length = ARRAY_SIZE(dispc_mgr_gamma_default_lut);
+ }
+
+ for (i = 0; i < length - 1; ++i) {
+ uint first = i * (gdesc->len - 1) / (length - 1);
+ uint last = (i + 1) * (gdesc->len - 1) / (length - 1);
+ uint w = last - first;
+ u16 r, g, b;
+ uint j;
+
+ if (w == 0)
+ continue;
+
+ for (j = 0; j <= w; j++) {
+ r = (lut[i].red * (w - j) + lut[i+1].red * j) / w;
+ g = (lut[i].green * (w - j) + lut[i+1].green * j) / w;
+ b = (lut[i].blue * (w - j) + lut[i+1].blue * j) / w;
+
+ r >>= 16 - gdesc->bits;
+ g >>= 16 - gdesc->bits;
+ b >>= 16 - gdesc->bits;
+
+ table[first + j] = (r << (gdesc->bits * 2)) |
+ (g << gdesc->bits) | b;
+ }
+ }
+
+ if (dispc.is_enabled)
+ dispc_mgr_write_gamma_table(channel);
+}
+EXPORT_SYMBOL(dispc_mgr_set_gamma);
+
+static int dispc_init_gamma_tables(void)
+{
+ int channel;
+
+ if (!dispc.feat->has_gamma_table)
+ return 0;
+
+ for (channel = 0; channel < ARRAY_SIZE(dispc.gamma_table); channel++) {
+ const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
+ u32 *gt;
+
+ if (channel == OMAP_DSS_CHANNEL_LCD2 &&
+ !dss_has_feature(FEAT_MGR_LCD2))
+ continue;
+
+ if (channel == OMAP_DSS_CHANNEL_LCD3 &&
+ !dss_has_feature(FEAT_MGR_LCD3))
+ continue;
+
+ gt = devm_kmalloc_array(&dispc.pdev->dev, gdesc->len,
+ sizeof(u32), GFP_KERNEL);
+ if (!gt)
+ return -ENOMEM;
+
+ dispc.gamma_table[channel] = gt;
+
+ dispc_mgr_set_gamma(channel, NULL, 0);
+ }
+ return 0;
+}
+
static void _omap_dispc_initial_config(void)
{
u32 l;
@@ -3829,8 +3963,15 @@ static void _omap_dispc_initial_config(void)
dispc.core_clk_rate = dispc_fclk_rate();
}
- /* FUNCGATED */
- if (dss_has_feature(FEAT_FUNCGATED))
+ /* Use gamma table mode, instead of palette mode */
+ if (dispc.feat->has_gamma_table)
+ REG_FLD_MOD(DISPC_CONFIG, 1, 3, 3);
+
+ /* For older DSS versions (FEAT_FUNCGATED) this enables
+ * func-clock auto-gating. For newer versions
+ * (dispc.feat->has_gamma_table) this enables tv-out gamma tables.
+ */
+ if (dss_has_feature(FEAT_FUNCGATED) || dispc.feat->has_gamma_table)
REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
dispc_setup_color_conv_coef();
@@ -3934,6 +4075,8 @@ static const struct dispc_features omap44xx_dispc_feats = {
.has_writeback = true,
.supports_double_pixel = true,
.reverse_ilace_field_order = true,
+ .has_gamma_table = true,
+ .has_gamma_i734_bug = true,
};
static const struct dispc_features omap54xx_dispc_feats = {
@@ -3959,6 +4102,8 @@ static const struct dispc_features omap54xx_dispc_feats = {
.has_writeback = true,
.supports_double_pixel = true,
.reverse_ilace_field_order = true,
+ .has_gamma_table = true,
+ .has_gamma_i734_bug = true,
};
static int dispc_init_features(struct platform_device *pdev)
@@ -4050,6 +4195,168 @@ void dispc_free_irq(void *dev_id)
}
EXPORT_SYMBOL(dispc_free_irq);
+/*
+ * Workaround for errata i734 in DSS dispc
+ * - LCD1 Gamma Correction Is Not Working When GFX Pipe Is Disabled
+ *
+ * For gamma tables to work on LCD1 the GFX plane has to be used at
+ * least once after DSS HW has come out of reset. The workaround
+ * sets up a minimal LCD setup with GFX plane and waits for one
+ * vertical sync irq before disabling the setup and continuing with
+ * the context restore. The physical outputs are gated during the
+ * operation. This workaround requires that gamma table's LOADMODE
+ * is set to 0x2 in DISPC_CONTROL1 register.
+ *
+ * For details see:
+ * OMAP543x Multimedia Device Silicon Revision 2.0 Silicon Errata
+ * Literature Number: SWPZ037E
+ * Or some other relevant errata document for the DSS IP version.
+ */
+
+static const struct dispc_errata_i734_data {
+ struct omap_video_timings timings;
+ struct omap_overlay_info ovli;
+ struct omap_overlay_manager_info mgri;
+ struct dss_lcd_mgr_config lcd_conf;
+} i734 = {
+ .timings = {
+ .x_res = 8, .y_res = 1,
+ .pixelclock = 16000000,
+ .hsw = 8, .hfp = 4, .hbp = 4,
+ .vsw = 1, .vfp = 1, .vbp = 1,
+ .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+ .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+ .interlace = false,
+ .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
+ .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ .double_pixel = false,
+ },
+ .ovli = {
+ .screen_width = 1,
+ .width = 1, .height = 1,
+ .color_mode = OMAP_DSS_COLOR_RGB24U,
+ .rotation = OMAP_DSS_ROT_0,
+ .rotation_type = OMAP_DSS_ROT_DMA,
+ .mirror = 0,
+ .pos_x = 0, .pos_y = 0,
+ .out_width = 0, .out_height = 0,
+ .global_alpha = 0xff,
+ .pre_mult_alpha = 0,
+ .zorder = 0,
+ },
+ .mgri = {
+ .default_color = 0,
+ .trans_enabled = false,
+ .partial_alpha_enabled = false,
+ .cpr_enable = false,
+ },
+ .lcd_conf = {
+ .io_pad_mode = DSS_IO_PAD_MODE_BYPASS,
+ .stallmode = false,
+ .fifohandcheck = false,
+ .clock_info = {
+ .lck_div = 1,
+ .pck_div = 2,
+ },
+ .video_port_width = 24,
+ .lcden_sig_polarity = 0,
+ },
+};
+
+static struct i734_buf {
+ size_t size;
+ dma_addr_t paddr;
+ void *vaddr;
+} i734_buf;
+
+static int dispc_errata_i734_wa_init(void)
+{
+ if (!dispc.feat->has_gamma_i734_bug)
+ return 0;
+
+ i734_buf.size = i734.ovli.width * i734.ovli.height *
+ color_mode_to_bpp(i734.ovli.color_mode) / 8;
+
+ i734_buf.vaddr = dma_alloc_writecombine(&dispc.pdev->dev, i734_buf.size,
+ &i734_buf.paddr, GFP_KERNEL);
+ if (!i734_buf.vaddr) {
+ dev_err(&dispc.pdev->dev, "%s: dma_alloc_writecombine failed",
+ __func__);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void dispc_errata_i734_wa_fini(void)
+{
+ if (!dispc.feat->has_gamma_i734_bug)
+ return;
+
+ dma_free_writecombine(&dispc.pdev->dev, i734_buf.size, i734_buf.vaddr,
+ i734_buf.paddr);
+}
+
+static void dispc_errata_i734_wa(void)
+{
+ u32 framedone_irq = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_LCD);
+ struct omap_overlay_info ovli;
+ struct dss_lcd_mgr_config lcd_conf;
+ u32 gatestate;
+ unsigned int count;
+
+ if (!dispc.feat->has_gamma_i734_bug)
+ return;
+
+ gatestate = REG_GET(DISPC_CONFIG, 8, 4);
+
+ ovli = i734.ovli;
+ ovli.paddr = i734_buf.paddr;
+ lcd_conf = i734.lcd_conf;
+
+ /* Gate all LCD1 outputs */
+ REG_FLD_MOD(DISPC_CONFIG, 0x1f, 8, 4);
+
+ /* Setup and enable GFX plane */
+ dispc_ovl_set_channel_out(OMAP_DSS_GFX, OMAP_DSS_CHANNEL_LCD);
+ dispc_ovl_setup(OMAP_DSS_GFX, &ovli, false, &i734.timings, false);
+ dispc_ovl_enable(OMAP_DSS_GFX, true);
+
+ /* Set up and enable display manager for LCD1 */
+ dispc_mgr_setup(OMAP_DSS_CHANNEL_LCD, &i734.mgri);
+ dispc_calc_clock_rates(dss_get_dispc_clk_rate(),
+ &lcd_conf.clock_info);
+ dispc_mgr_set_lcd_config(OMAP_DSS_CHANNEL_LCD, &lcd_conf);
+ dispc_mgr_set_timings(OMAP_DSS_CHANNEL_LCD, &i734.timings);
+
+ dispc_clear_irqstatus(framedone_irq);
+
+ /* Enable and shut the channel to produce just one frame */
+ dispc_mgr_enable(OMAP_DSS_CHANNEL_LCD, true);
+ dispc_mgr_enable(OMAP_DSS_CHANNEL_LCD, false);
+
+ /* Busy wait for framedone. We can't fiddle with irq handlers
+ * in PM resume. Typically the loop runs less than 5 times and
+ * waits less than a micro second.
+ */
+ count = 0;
+ while (!(dispc_read_irqstatus() & framedone_irq)) {
+ if (count++ > 10000) {
+ dev_err(&dispc.pdev->dev, "%s: framedone timeout\n",
+ __func__);
+ break;
+ }
+ }
+ dispc_ovl_enable(OMAP_DSS_GFX, false);
+
+ /* Clear all irq bits before continuing */
+ dispc_clear_irqstatus(0xffffffff);
+
+ /* Restore the original state to LCD1 output gates */
+ REG_FLD_MOD(DISPC_CONFIG, gatestate, 8, 4);
+}
+
/* DISPC HW IP initialisation */
static int dispc_bind(struct device *dev, struct device *master, void *data)
{
@@ -4067,6 +4374,10 @@ static int dispc_bind(struct device *dev, struct device *master, void *data)
if (r)
return r;
+ r = dispc_errata_i734_wa_init();
+ if (r)
+ return r;
+
dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
if (!dispc_mem) {
DSSERR("can't get IORESOURCE_MEM DISPC\n");
@@ -4100,6 +4411,10 @@ static int dispc_bind(struct device *dev, struct device *master, void *data)
}
}
+ r = dispc_init_gamma_tables();
+ if (r)
+ return r;
+
pm_runtime_enable(&pdev->dev);
r = dispc_runtime_get();
@@ -4127,6 +4442,8 @@ static void dispc_unbind(struct device *dev, struct device *master,
void *data)
{
pm_runtime_disable(dev);
+
+ dispc_errata_i734_wa_fini();
}
static const struct component_ops dispc_component_ops = {
@@ -4169,7 +4486,11 @@ static int dispc_runtime_resume(struct device *dev)
if (REG_GET(DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) {
_omap_dispc_initial_config();
+ dispc_errata_i734_wa();
+
dispc_restore_context();
+
+ dispc_restore_gamma_tables();
}
dispc.is_enabled = true;
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.h b/drivers/gpu/drm/omapdrm/dss/dispc.h
index 483744223dd1..bc1d8126ee87 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.h
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.h
@@ -42,6 +42,11 @@
#define DISPC_MSTANDBY_CTRL 0x0858
#define DISPC_GLOBAL_MFLAG_ATTRIBUTE 0x085C
+#define DISPC_GAMMA_TABLE0 0x0630
+#define DISPC_GAMMA_TABLE1 0x0634
+#define DISPC_GAMMA_TABLE2 0x0638
+#define DISPC_GAMMA_TABLE3 0x0850
+
/* DISPC overlay registers */
#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
DISPC_BA0_OFFSET(n))
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc_coefs.c b/drivers/gpu/drm/omapdrm/dss/dispc_coefs.c
index 038c15b04215..34fad2376f8d 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc_coefs.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc_coefs.c
@@ -18,8 +18,8 @@
*/
#include <linux/kernel.h>
-#include <video/omapdss.h>
+#include "omapdss.h"
#include "dispc.h"
static const struct dispc_coef coef3_M8[8] = {
diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c
index 9f3dd09b0a6c..8dcdd7cf9937 100644
--- a/drivers/gpu/drm/omapdrm/dss/display.c
+++ b/drivers/gpu/drm/omapdrm/dss/display.c
@@ -28,7 +28,7 @@
#include <linux/platform_device.h>
#include <linux/of.h>
-#include <video/omapdss.h>
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 97ea60257884..b268295b76cf 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -34,17 +34,15 @@
#include <linux/clk.h>
#include <linux/component.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
-#define HSDIV_DISPC 0
-
struct dpi_data {
struct platform_device *pdev;
struct regulator *vdds_dsi_reg;
+ enum dss_clk_source clk_src;
struct dss_pll *pll;
struct mutex lock;
@@ -69,7 +67,7 @@ static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev)
return dev_get_drvdata(&pdev->dev);
}
-static struct dss_pll *dpi_get_pll(enum omap_channel channel)
+static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel)
{
/*
* XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
@@ -83,64 +81,51 @@ static struct dss_pll *dpi_get_pll(enum omap_channel channel)
case OMAPDSS_VER_OMAP3630:
case OMAPDSS_VER_AM35xx:
case OMAPDSS_VER_AM43xx:
- return NULL;
+ return DSS_CLK_SRC_FCK;
case OMAPDSS_VER_OMAP4430_ES1:
case OMAPDSS_VER_OMAP4430_ES2:
case OMAPDSS_VER_OMAP4:
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
- return dss_pll_find("dsi0");
+ return DSS_CLK_SRC_PLL1_1;
case OMAP_DSS_CHANNEL_LCD2:
- return dss_pll_find("dsi1");
+ return DSS_CLK_SRC_PLL2_1;
default:
- return NULL;
+ return DSS_CLK_SRC_FCK;
}
case OMAPDSS_VER_OMAP5:
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
- return dss_pll_find("dsi0");
+ return DSS_CLK_SRC_PLL1_1;
case OMAP_DSS_CHANNEL_LCD3:
- return dss_pll_find("dsi1");
+ return DSS_CLK_SRC_PLL2_1;
+ case OMAP_DSS_CHANNEL_LCD2:
default:
- return NULL;
+ return DSS_CLK_SRC_FCK;
}
case OMAPDSS_VER_DRA7xx:
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
+ return DSS_CLK_SRC_PLL1_1;
case OMAP_DSS_CHANNEL_LCD2:
- return dss_pll_find("video0");
+ return DSS_CLK_SRC_PLL1_3;
case OMAP_DSS_CHANNEL_LCD3:
- return dss_pll_find("video1");
+ return DSS_CLK_SRC_PLL2_1;
default:
- return NULL;
+ return DSS_CLK_SRC_FCK;
}
default:
- return NULL;
- }
-}
-
-static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
-{
- switch (channel) {
- case OMAP_DSS_CHANNEL_LCD:
- return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
- case OMAP_DSS_CHANNEL_LCD2:
- return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
- case OMAP_DSS_CHANNEL_LCD3:
- return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
- default:
- /* this shouldn't happen */
- WARN_ON(1);
- return OMAP_DSS_CLK_SRC_FCK;
+ return DSS_CLK_SRC_FCK;
}
}
struct dpi_clk_calc_ctx {
struct dss_pll *pll;
+ unsigned clkout_idx;
/* inputs */
@@ -148,7 +133,7 @@ struct dpi_clk_calc_ctx {
/* outputs */
- struct dss_pll_clock_info dsi_cinfo;
+ struct dss_pll_clock_info pll_cinfo;
unsigned long fck;
struct dispc_clock_info dispc_cinfo;
};
@@ -193,8 +178,8 @@ static bool dpi_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000)
return false;
- ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc;
- ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc;
+ ctx->pll_cinfo.mX[ctx->clkout_idx] = m_dispc;
+ ctx->pll_cinfo.clkout[ctx->clkout_idx] = dispc;
return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
dpi_calc_dispc_cb, ctx);
@@ -207,12 +192,12 @@ static bool dpi_calc_pll_cb(int n, int m, unsigned long fint,
{
struct dpi_clk_calc_ctx *ctx = data;
- ctx->dsi_cinfo.n = n;
- ctx->dsi_cinfo.m = m;
- ctx->dsi_cinfo.fint = fint;
- ctx->dsi_cinfo.clkdco = clkdco;
+ ctx->pll_cinfo.n = n;
+ ctx->pll_cinfo.m = m;
+ ctx->pll_cinfo.fint = fint;
+ ctx->pll_cinfo.clkdco = clkdco;
- return dss_pll_hsdiv_calc(ctx->pll, clkdco,
+ return dss_pll_hsdiv_calc_a(ctx->pll, clkdco,
ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
dpi_calc_hsdiv_cb, ctx);
}
@@ -227,25 +212,39 @@ static bool dpi_calc_dss_cb(unsigned long fck, void *data)
dpi_calc_dispc_cb, ctx);
}
-static bool dpi_dsi_clk_calc(struct dpi_data *dpi, unsigned long pck,
+static bool dpi_pll_clk_calc(struct dpi_data *dpi, unsigned long pck,
struct dpi_clk_calc_ctx *ctx)
{
unsigned long clkin;
- unsigned long pll_min, pll_max;
memset(ctx, 0, sizeof(*ctx));
ctx->pll = dpi->pll;
- ctx->pck_min = pck - 1000;
- ctx->pck_max = pck + 1000;
+ ctx->clkout_idx = dss_pll_get_clkout_idx_for_src(dpi->clk_src);
- pll_min = 0;
- pll_max = 0;
+ clkin = clk_get_rate(dpi->pll->clkin);
- clkin = clk_get_rate(ctx->pll->clkin);
+ if (dpi->pll->hw->type == DSS_PLL_TYPE_A) {
+ unsigned long pll_min, pll_max;
- return dss_pll_calc(ctx->pll, clkin,
- pll_min, pll_max,
- dpi_calc_pll_cb, ctx);
+ ctx->pck_min = pck - 1000;
+ ctx->pck_max = pck + 1000;
+
+ pll_min = 0;
+ pll_max = 0;
+
+ return dss_pll_calc_a(ctx->pll, clkin,
+ pll_min, pll_max,
+ dpi_calc_pll_cb, ctx);
+ } else { /* DSS_PLL_TYPE_B */
+ dss_pll_calc_b(dpi->pll, clkin, pck, &ctx->pll_cinfo);
+
+ ctx->dispc_cinfo.lck_div = 1;
+ ctx->dispc_cinfo.pck_div = 1;
+ ctx->dispc_cinfo.lck = ctx->pll_cinfo.clkout[0];
+ ctx->dispc_cinfo.pck = ctx->dispc_cinfo.lck;
+
+ return true;
+ }
}
static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
@@ -279,7 +278,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
-static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel,
+static int dpi_set_pll_clk(struct dpi_data *dpi, enum omap_channel channel,
unsigned long pck_req, unsigned long *fck, int *lck_div,
int *pck_div)
{
@@ -287,20 +286,19 @@ static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel,
int r;
bool ok;
- ok = dpi_dsi_clk_calc(dpi, pck_req, &ctx);
+ ok = dpi_pll_clk_calc(dpi, pck_req, &ctx);
if (!ok)
return -EINVAL;
- r = dss_pll_set_config(dpi->pll, &ctx.dsi_cinfo);
+ r = dss_pll_set_config(dpi->pll, &ctx.pll_cinfo);
if (r)
return r;
- dss_select_lcd_clk_source(channel,
- dpi_get_alt_clk_src(channel));
+ dss_select_lcd_clk_source(channel, dpi->clk_src);
dpi->mgr_config.clock_info = ctx.dispc_cinfo;
- *fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC];
+ *fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
*lck_div = ctx.dispc_cinfo.lck_div;
*pck_div = ctx.dispc_cinfo.pck_div;
@@ -342,7 +340,7 @@ static int dpi_set_mode(struct dpi_data *dpi)
int r = 0;
if (dpi->pll)
- r = dpi_set_dsi_clk(dpi, channel, t->pixelclock, &fck,
+ r = dpi_set_pll_clk(dpi, channel, t->pixelclock, &fck,
&lck_div, &pck_div);
else
r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
@@ -419,7 +417,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
if (dpi->pll) {
r = dss_pll_enable(dpi->pll);
if (r)
- goto err_dsi_pll_init;
+ goto err_pll_init;
}
r = dpi_set_mode(dpi);
@@ -442,7 +440,7 @@ err_mgr_enable:
err_set_mode:
if (dpi->pll)
dss_pll_disable(dpi->pll);
-err_dsi_pll_init:
+err_pll_init:
err_src_sel:
dispc_runtime_put();
err_get_dispc:
@@ -465,7 +463,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
dss_mgr_disable(channel);
if (dpi->pll) {
- dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK);
+ dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
dss_pll_disable(dpi->pll);
}
@@ -524,11 +522,11 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
return -EINVAL;
if (dpi->pll) {
- ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx);
+ ok = dpi_pll_clk_calc(dpi, timings->pixelclock, &ctx);
if (!ok)
return -EINVAL;
- fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC];
+ fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
} else {
ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
if (!ok)
@@ -558,7 +556,7 @@ static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
mutex_unlock(&dpi->lock);
}
-static int dpi_verify_dsi_pll(struct dss_pll *pll)
+static int dpi_verify_pll(struct dss_pll *pll)
{
int r;
@@ -602,16 +600,14 @@ static void dpi_init_pll(struct dpi_data *dpi)
if (dpi->pll)
return;
- pll = dpi_get_pll(dpi->output.dispc_channel);
+ dpi->clk_src = dpi_get_clk_src(dpi->output.dispc_channel);
+
+ pll = dss_pll_find_by_src(dpi->clk_src);
if (!pll)
return;
- /* On DRA7 we need to set a mux to use the PLL */
- if (omapdss_get_version() == OMAPDSS_VER_DRA7xx)
- dss_ctrl_pll_set_control_mux(pll->id, dpi->output.dispc_channel);
-
- if (dpi_verify_dsi_pll(pll)) {
- DSSWARN("DSI PLL not operational\n");
+ if (dpi_verify_pll(pll)) {
+ DSSWARN("PLL not operational\n");
return;
}
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 9ed8272e54ae..6f45e9d00b41 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -42,9 +42,9 @@
#include <linux/of_platform.h>
#include <linux/component.h>
-#include <video/omapdss.h>
#include <video/mipi_display.h>
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
@@ -1262,7 +1262,7 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
unsigned long r;
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) {
+ if (dss_get_dsi_clk_source(dsi->module_id) == DSS_CLK_SRC_FCK) {
/* DSI FCLK source is DSS_CLK_FCK */
r = clk_get_rate(dsi->dss_clk);
} else {
@@ -1475,7 +1475,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
- enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
+ enum dss_clk_source dispc_clk_src, dsi_clk_src;
int dsi_module = dsi->module_id;
struct dss_pll *pll = &dsi->pll;
@@ -1495,28 +1495,27 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
cinfo->clkdco, cinfo->m);
seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16lum_dispc %u\t(%s)\n",
- dss_feat_get_clk_source_name(dsi_module == 0 ?
- OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
- OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
+ dss_get_clk_source_name(dsi_module == 0 ?
+ DSS_CLK_SRC_PLL1_1 :
+ DSS_CLK_SRC_PLL2_1),
cinfo->clkout[HSDIV_DISPC],
cinfo->mX[HSDIV_DISPC],
- dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
+ dispc_clk_src == DSS_CLK_SRC_FCK ?
"off" : "on");
seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16lum_dsi %u\t(%s)\n",
- dss_feat_get_clk_source_name(dsi_module == 0 ?
- OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
- OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
+ dss_get_clk_source_name(dsi_module == 0 ?
+ DSS_CLK_SRC_PLL1_2 :
+ DSS_CLK_SRC_PLL2_2),
cinfo->clkout[HSDIV_DSI],
cinfo->mX[HSDIV_DSI],
- dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
+ dsi_clk_src == DSS_CLK_SRC_FCK ?
"off" : "on");
seq_printf(s, "- DSI%d -\n", dsi_module + 1);
- seq_printf(s, "dsi fclk source = %s (%s)\n",
- dss_get_generic_clk_source_name(dsi_clk_src),
- dss_feat_get_clk_source_name(dsi_clk_src));
+ seq_printf(s, "dsi fclk source = %s\n",
+ dss_get_clk_source_name(dsi_clk_src));
seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
@@ -4102,8 +4101,8 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
int r;
dss_select_lcd_clk_source(channel, dsi->module_id == 0 ?
- OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
- OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
+ DSS_CLK_SRC_PLL1_1 :
+ DSS_CLK_SRC_PLL2_1);
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
r = dss_mgr_register_framedone_handler(channel,
@@ -4150,7 +4149,7 @@ err1:
dss_mgr_unregister_framedone_handler(channel,
dsi_framedone_irq_callback, dsidev);
err:
- dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK);
+ dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
return r;
}
@@ -4163,7 +4162,7 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
dss_mgr_unregister_framedone_handler(channel,
dsi_framedone_irq_callback, dsidev);
- dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK);
+ dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
}
static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
@@ -4197,8 +4196,8 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
goto err1;
dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
- OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
- OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI);
+ DSS_CLK_SRC_PLL1_2 :
+ DSS_CLK_SRC_PLL2_2);
DSSDBG("PLL OK\n");
@@ -4230,7 +4229,7 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
err3:
dsi_cio_uninit(dsidev);
err2:
- dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
+ dss_select_dsi_clk_source(dsi->module_id, DSS_CLK_SRC_FCK);
err1:
dss_pll_disable(&dsi->pll);
err0:
@@ -4252,7 +4251,7 @@ static void dsi_display_uninit_dsi(struct platform_device *dsidev,
dsi_vc_enable(dsidev, 2, 0);
dsi_vc_enable(dsidev, 3, 0);
- dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
+ dss_select_dsi_clk_source(dsi->module_id, DSS_CLK_SRC_FCK);
dsi_cio_uninit(dsidev);
dsi_pll_uninit(dsidev, disconnect_lanes);
}
@@ -4453,7 +4452,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
ctx->dsi_cinfo.fint = fint;
ctx->dsi_cinfo.clkdco = clkdco;
- return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min,
+ return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min,
dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
dsi_cm_calc_hsdiv_cb, ctx);
}
@@ -4492,7 +4491,7 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
pll_max = cfg->hs_clk_max * 4;
- return dss_pll_calc(ctx->pll, clkin,
+ return dss_pll_calc_a(ctx->pll, clkin,
pll_min, pll_max,
dsi_cm_calc_pll_cb, ctx);
}
@@ -4751,7 +4750,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
ctx->dsi_cinfo.fint = fint;
ctx->dsi_cinfo.clkdco = clkdco;
- return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min,
+ return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min,
dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
dsi_vm_calc_hsdiv_cb, ctx);
}
@@ -4793,7 +4792,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
pll_max = byteclk_max * 4 * 4;
}
- return dss_pll_calc(ctx->pll, clkin,
+ return dss_pll_calc_a(ctx->pll, clkin,
pll_min, pll_max,
dsi_vm_calc_pll_cb, ctx);
}
@@ -5139,6 +5138,8 @@ static const struct dss_pll_ops dsi_pll_ops = {
};
static const struct dss_pll_hw dss_omap3_dsi_pll_hw = {
+ .type = DSS_PLL_TYPE_A,
+
.n_max = (1 << 7) - 1,
.m_max = (1 << 11) - 1,
.mX_max = (1 << 4) - 1,
@@ -5164,6 +5165,8 @@ static const struct dss_pll_hw dss_omap3_dsi_pll_hw = {
};
static const struct dss_pll_hw dss_omap4_dsi_pll_hw = {
+ .type = DSS_PLL_TYPE_A,
+
.n_max = (1 << 8) - 1,
.m_max = (1 << 12) - 1,
.mX_max = (1 << 5) - 1,
@@ -5189,6 +5192,8 @@ static const struct dss_pll_hw dss_omap4_dsi_pll_hw = {
};
static const struct dss_pll_hw dss_omap5_dsi_pll_hw = {
+ .type = DSS_PLL_TYPE_A,
+
.n_max = (1 << 8) - 1,
.m_max = (1 << 12) - 1,
.mX_max = (1 << 5) - 1,
diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c b/drivers/gpu/drm/omapdrm/dss/dss-of.c
index bf407b6ba15c..dfd4e9621e3b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss-of.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss-of.c
@@ -18,8 +18,7 @@
#include <linux/of.h>
#include <linux/seq_file.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
struct device_node *
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 3303cfad4838..14887d5b02e5 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -42,8 +42,7 @@
#include <linux/suspend.h>
#include <linux/component.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
@@ -76,6 +75,8 @@ struct dss_features {
const enum omap_display_type *ports;
int num_ports;
int (*dpi_select_source)(int port, enum omap_channel channel);
+ int (*select_lcd_source)(enum omap_channel channel,
+ enum dss_clk_source clk_src);
};
static struct {
@@ -92,9 +93,9 @@ static struct {
unsigned long cache_prate;
struct dispc_clock_info cache_dispc_cinfo;
- enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
- enum omap_dss_clk_source dispc_clk_source;
- enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
+ enum dss_clk_source dsi_clk_source[MAX_NUM_DSI];
+ enum dss_clk_source dispc_clk_source;
+ enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
bool ctx_valid;
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
@@ -106,11 +107,14 @@ static struct {
} dss;
static const char * const dss_generic_clk_source_names[] = {
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
- [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
- [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
- [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
+ [DSS_CLK_SRC_FCK] = "FCK",
+ [DSS_CLK_SRC_PLL1_1] = "PLL1:1",
+ [DSS_CLK_SRC_PLL1_2] = "PLL1:2",
+ [DSS_CLK_SRC_PLL1_3] = "PLL1:3",
+ [DSS_CLK_SRC_PLL2_1] = "PLL2:1",
+ [DSS_CLK_SRC_PLL2_2] = "PLL2:2",
+ [DSS_CLK_SRC_PLL2_3] = "PLL2:3",
+ [DSS_CLK_SRC_HDMI_PLL] = "HDMI PLL",
};
static bool dss_initialized;
@@ -203,68 +207,70 @@ void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable)
1 << shift, val << shift);
}
-void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
+static int dss_ctrl_pll_set_control_mux(enum dss_clk_source clk_src,
enum omap_channel channel)
{
unsigned shift, val;
if (!dss.syscon_pll_ctrl)
- return;
+ return -EINVAL;
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
shift = 3;
- switch (pll_id) {
- case DSS_PLL_VIDEO1:
+ switch (clk_src) {
+ case DSS_CLK_SRC_PLL1_1:
val = 0; break;
- case DSS_PLL_HDMI:
+ case DSS_CLK_SRC_HDMI_PLL:
val = 1; break;
default:
DSSERR("error in PLL mux config for LCD\n");
- return;
+ return -EINVAL;
}
break;
case OMAP_DSS_CHANNEL_LCD2:
shift = 5;
- switch (pll_id) {
- case DSS_PLL_VIDEO1:
+ switch (clk_src) {
+ case DSS_CLK_SRC_PLL1_3:
val = 0; break;
- case DSS_PLL_VIDEO2:
+ case DSS_CLK_SRC_PLL2_3:
val = 1; break;
- case DSS_PLL_HDMI:
+ case DSS_CLK_SRC_HDMI_PLL:
val = 2; break;
default:
DSSERR("error in PLL mux config for LCD2\n");
- return;
+ return -EINVAL;
}
break;
case OMAP_DSS_CHANNEL_LCD3:
shift = 7;
- switch (pll_id) {
- case DSS_PLL_VIDEO1:
- val = 1; break;
- case DSS_PLL_VIDEO2:
+ switch (clk_src) {
+ case DSS_CLK_SRC_PLL2_1:
val = 0; break;
- case DSS_PLL_HDMI:
+ case DSS_CLK_SRC_PLL1_3:
+ val = 1; break;
+ case DSS_CLK_SRC_HDMI_PLL:
val = 2; break;
default:
DSSERR("error in PLL mux config for LCD3\n");
- return;
+ return -EINVAL;
}
break;
default:
DSSERR("error in PLL mux config\n");
- return;
+ return -EINVAL;
}
regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
0x3 << shift, val << shift);
+
+ return 0;
}
void dss_sdi_init(int datapairs)
@@ -354,14 +360,14 @@ void dss_sdi_disable(void)
REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
}
-const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
+const char *dss_get_clk_source_name(enum dss_clk_source clk_src)
{
return dss_generic_clk_source_names[clk_src];
}
void dss_dump_clocks(struct seq_file *s)
{
- const char *fclk_name, *fclk_real_name;
+ const char *fclk_name;
unsigned long fclk_rate;
if (dss_runtime_get())
@@ -369,12 +375,11 @@ void dss_dump_clocks(struct seq_file *s)
seq_printf(s, "- DSS -\n");
- fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
- fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
+ fclk_name = dss_get_clk_source_name(DSS_CLK_SRC_FCK);
fclk_rate = clk_get_rate(dss.dss_clk);
- seq_printf(s, "%s (%s) = %lu\n",
- fclk_name, fclk_real_name,
+ seq_printf(s, "%s = %lu\n",
+ fclk_name,
fclk_rate);
dss_runtime_put();
@@ -403,19 +408,42 @@ static void dss_dump_regs(struct seq_file *s)
#undef DUMPREG
}
-static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
+static int dss_get_channel_index(enum omap_channel channel)
+{
+ switch (channel) {
+ case OMAP_DSS_CHANNEL_LCD:
+ return 0;
+ case OMAP_DSS_CHANNEL_LCD2:
+ return 1;
+ case OMAP_DSS_CHANNEL_LCD3:
+ return 2;
+ default:
+ WARN_ON(1);
+ return 0;
+ }
+}
+
+static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
{
int b;
u8 start, end;
+ /*
+ * We always use PRCM clock as the DISPC func clock, except on DSS3,
+ * where we don't have separate DISPC and LCD clock sources.
+ */
+ if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) &&
+ clk_src != DSS_CLK_SRC_FCK))
+ return;
+
switch (clk_src) {
- case OMAP_DSS_CLK_SRC_FCK:
+ case DSS_CLK_SRC_FCK:
b = 0;
break;
- case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+ case DSS_CLK_SRC_PLL1_1:
b = 1;
break;
- case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+ case DSS_CLK_SRC_PLL2_1:
b = 2;
break;
default:
@@ -431,19 +459,19 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
}
void dss_select_dsi_clk_source(int dsi_module,
- enum omap_dss_clk_source clk_src)
+ enum dss_clk_source clk_src)
{
int b, pos;
switch (clk_src) {
- case OMAP_DSS_CLK_SRC_FCK:
+ case DSS_CLK_SRC_FCK:
b = 0;
break;
- case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
+ case DSS_CLK_SRC_PLL1_2:
BUG_ON(dsi_module != 0);
b = 1;
break;
- case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
+ case DSS_CLK_SRC_PLL2_2:
BUG_ON(dsi_module != 1);
b = 1;
break;
@@ -458,59 +486,125 @@ void dss_select_dsi_clk_source(int dsi_module,
dss.dsi_clk_source[dsi_module] = clk_src;
}
+static int dss_lcd_clk_mux_dra7(enum omap_channel channel,
+ enum dss_clk_source clk_src)
+{
+ const u8 ctrl_bits[] = {
+ [OMAP_DSS_CHANNEL_LCD] = 0,
+ [OMAP_DSS_CHANNEL_LCD2] = 12,
+ [OMAP_DSS_CHANNEL_LCD3] = 19,
+ };
+
+ u8 ctrl_bit = ctrl_bits[channel];
+ int r;
+
+ if (clk_src == DSS_CLK_SRC_FCK) {
+ /* LCDx_CLK_SWITCH */
+ REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
+ return -EINVAL;
+ }
+
+ r = dss_ctrl_pll_set_control_mux(clk_src, channel);
+ if (r)
+ return r;
+
+ REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
+
+ return 0;
+}
+
+static int dss_lcd_clk_mux_omap5(enum omap_channel channel,
+ enum dss_clk_source clk_src)
+{
+ const u8 ctrl_bits[] = {
+ [OMAP_DSS_CHANNEL_LCD] = 0,
+ [OMAP_DSS_CHANNEL_LCD2] = 12,
+ [OMAP_DSS_CHANNEL_LCD3] = 19,
+ };
+ const enum dss_clk_source allowed_plls[] = {
+ [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
+ [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_FCK,
+ [OMAP_DSS_CHANNEL_LCD3] = DSS_CLK_SRC_PLL2_1,
+ };
+
+ u8 ctrl_bit = ctrl_bits[channel];
+
+ if (clk_src == DSS_CLK_SRC_FCK) {
+ /* LCDx_CLK_SWITCH */
+ REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
+ return -EINVAL;
+ }
+
+ if (WARN_ON(allowed_plls[channel] != clk_src))
+ return -EINVAL;
+
+ REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
+
+ return 0;
+}
+
+static int dss_lcd_clk_mux_omap4(enum omap_channel channel,
+ enum dss_clk_source clk_src)
+{
+ const u8 ctrl_bits[] = {
+ [OMAP_DSS_CHANNEL_LCD] = 0,
+ [OMAP_DSS_CHANNEL_LCD2] = 12,
+ };
+ const enum dss_clk_source allowed_plls[] = {
+ [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
+ [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_PLL2_1,
+ };
+
+ u8 ctrl_bit = ctrl_bits[channel];
+
+ if (clk_src == DSS_CLK_SRC_FCK) {
+ /* LCDx_CLK_SWITCH */
+ REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
+ return 0;
+ }
+
+ if (WARN_ON(allowed_plls[channel] != clk_src))
+ return -EINVAL;
+
+ REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
+
+ return 0;
+}
+
void dss_select_lcd_clk_source(enum omap_channel channel,
- enum omap_dss_clk_source clk_src)
+ enum dss_clk_source clk_src)
{
- int b, ix, pos;
+ int idx = dss_get_channel_index(channel);
+ int r;
if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
dss_select_dispc_clk_source(clk_src);
+ dss.lcd_clk_source[idx] = clk_src;
return;
}
- switch (clk_src) {
- case OMAP_DSS_CLK_SRC_FCK:
- b = 0;
- break;
- case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
- BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
- b = 1;
- break;
- case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
- BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
- channel != OMAP_DSS_CHANNEL_LCD3);
- b = 1;
- break;
- default:
- BUG();
+ r = dss.feat->select_lcd_source(channel, clk_src);
+ if (r)
return;
- }
-
- pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
- (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
- REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
- ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
- (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
- dss.lcd_clk_source[ix] = clk_src;
+ dss.lcd_clk_source[idx] = clk_src;
}
-enum omap_dss_clk_source dss_get_dispc_clk_source(void)
+enum dss_clk_source dss_get_dispc_clk_source(void)
{
return dss.dispc_clk_source;
}
-enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
+enum dss_clk_source dss_get_dsi_clk_source(int dsi_module)
{
return dss.dsi_clk_source[dsi_module];
}
-enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
+enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
{
if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
- int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
- (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
- return dss.lcd_clk_source[ix];
+ int idx = dss_get_channel_index(channel);
+ return dss.lcd_clk_source[idx];
} else {
/* LCD_CLK source is the same as DISPC_FCLK source for
* OMAP2 and OMAP3 */
@@ -859,6 +953,7 @@ static const struct dss_features omap44xx_dss_feats = {
.dpi_select_source = &dss_dpi_select_source_omap4,
.ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports),
+ .select_lcd_source = &dss_lcd_clk_mux_omap4,
};
static const struct dss_features omap54xx_dss_feats = {
@@ -868,6 +963,7 @@ static const struct dss_features omap54xx_dss_feats = {
.dpi_select_source = &dss_dpi_select_source_omap5,
.ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports),
+ .select_lcd_source = &dss_lcd_clk_mux_omap5,
};
static const struct dss_features am43xx_dss_feats = {
@@ -886,6 +982,7 @@ static const struct dss_features dra7xx_dss_feats = {
.dpi_select_source = &dss_dpi_select_source_dra7xx,
.ports = dra7xx_ports,
.num_ports = ARRAY_SIZE(dra7xx_ports),
+ .select_lcd_source = &dss_lcd_clk_mux_dra7,
};
static int dss_init_features(struct platform_device *pdev)
@@ -1143,18 +1240,18 @@ static int dss_bind(struct device *dev)
/* Select DPLL */
REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
- dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+ dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
#ifdef CONFIG_OMAP2_DSS_VENC
REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
#endif
- dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
- dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
- dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
- dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
- dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+ dss.dsi_clk_source[0] = DSS_CLK_SRC_FCK;
+ dss.dsi_clk_source[1] = DSS_CLK_SRC_FCK;
+ dss.dispc_clk_source = DSS_CLK_SRC_FCK;
+ dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
+ dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
rev = dss_read_reg(DSS_REVISION);
printk(KERN_INFO "OMAP DSS rev %d.%d\n",
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h
index 38e6ab50142d..4fd06dc41cb3 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.h
+++ b/drivers/gpu/drm/omapdrm/dss/dss.h
@@ -102,6 +102,20 @@ enum dss_writeback_channel {
DSS_WB_LCD3_MGR = 7,
};
+enum dss_clk_source {
+ DSS_CLK_SRC_FCK = 0,
+
+ DSS_CLK_SRC_PLL1_1,
+ DSS_CLK_SRC_PLL1_2,
+ DSS_CLK_SRC_PLL1_3,
+
+ DSS_CLK_SRC_PLL2_1,
+ DSS_CLK_SRC_PLL2_2,
+ DSS_CLK_SRC_PLL2_3,
+
+ DSS_CLK_SRC_HDMI_PLL,
+};
+
enum dss_pll_id {
DSS_PLL_DSI1,
DSS_PLL_DSI2,
@@ -114,6 +128,11 @@ struct dss_pll;
#define DSS_PLL_MAX_HSDIVS 4
+enum dss_pll_type {
+ DSS_PLL_TYPE_A,
+ DSS_PLL_TYPE_B,
+};
+
/*
* Type-A PLLs: clkout[]/mX[] refer to hsdiv outputs m4, m5, m6, m7.
* Type-B PLLs: clkout[0] refers to m2.
@@ -140,6 +159,8 @@ struct dss_pll_ops {
};
struct dss_pll_hw {
+ enum dss_pll_type type;
+
unsigned n_max;
unsigned m_min;
unsigned m_max;
@@ -227,7 +248,7 @@ unsigned long dss_get_dispc_clk_rate(void);
int dss_dpi_select_source(int port, enum omap_channel channel);
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
-const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
+const char *dss_get_clk_source_name(enum dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s);
/* DSS VIDEO PLL */
@@ -244,20 +265,18 @@ void dss_debug_dump_clocks(struct seq_file *s);
#endif
void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable);
-void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
- enum omap_channel channel);
void dss_sdi_init(int datapairs);
int dss_sdi_enable(void);
void dss_sdi_disable(void);
void dss_select_dsi_clk_source(int dsi_module,
- enum omap_dss_clk_source clk_src);
+ enum dss_clk_source clk_src);
void dss_select_lcd_clk_source(enum omap_channel channel,
- enum omap_dss_clk_source clk_src);
-enum omap_dss_clk_source dss_get_dispc_clk_source(void);
-enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module);
-enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
+ enum dss_clk_source clk_src);
+enum dss_clk_source dss_get_dispc_clk_source(void);
+enum dss_clk_source dss_get_dsi_clk_source(int dsi_module);
+enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
void dss_set_venc_output(enum omap_dss_venc_type type);
void dss_set_dac_pwrdn_bgz(bool enable);
@@ -409,17 +428,23 @@ typedef bool (*dss_hsdiv_calc_func)(int m_dispc, unsigned long dispc,
int dss_pll_register(struct dss_pll *pll);
void dss_pll_unregister(struct dss_pll *pll);
struct dss_pll *dss_pll_find(const char *name);
+struct dss_pll *dss_pll_find_by_src(enum dss_clk_source src);
+unsigned dss_pll_get_clkout_idx_for_src(enum dss_clk_source src);
int dss_pll_enable(struct dss_pll *pll);
void dss_pll_disable(struct dss_pll *pll);
int dss_pll_set_config(struct dss_pll *pll,
const struct dss_pll_clock_info *cinfo);
-bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
+bool dss_pll_hsdiv_calc_a(const struct dss_pll *pll, unsigned long clkdco,
unsigned long out_min, unsigned long out_max,
dss_hsdiv_calc_func func, void *data);
-bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
+bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
unsigned long pll_min, unsigned long pll_max,
dss_pll_calc_func func, void *data);
+
+bool dss_pll_calc_b(const struct dss_pll *pll, unsigned long clkin,
+ unsigned long target_clkout, struct dss_pll_clock_info *cinfo);
+
int dss_pll_write_config_type_a(struct dss_pll *pll,
const struct dss_pll_clock_info *cinfo);
int dss_pll_write_config_type_b(struct dss_pll *pll,
diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.c b/drivers/gpu/drm/omapdrm/dss/dss_features.c
index c886a2927f73..ee5b93ce2763 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss_features.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss_features.c
@@ -23,8 +23,7 @@
#include <linux/err.h>
#include <linux/slab.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
@@ -50,7 +49,6 @@ struct omap_dss_features {
const enum omap_dss_output_id *supported_outputs;
const enum omap_color_mode *supported_color_modes;
const enum omap_overlay_caps *overlay_caps;
- const char * const *clksrc_names;
const struct dss_param_range *dss_params;
const enum omap_dss_rotation_type supported_rotation_types;
@@ -389,34 +387,6 @@ static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
};
-static const char * const omap2_dss_clk_source_names[] = {
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A",
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A",
- [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1",
-};
-
-static const char * const omap3_dss_clk_source_names[] = {
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK",
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK",
- [OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK",
-};
-
-static const char * const omap4_dss_clk_source_names[] = {
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1",
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2",
- [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK",
- [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "PLL2_CLK1",
- [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
-};
-
-static const char * const omap5_dss_clk_source_names[] = {
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
- [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
- [OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
- [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
- [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
-};
-
static const struct dss_param_range omap2_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 133000000 },
[FEAT_PARAM_DSS_PCD] = { 2, 255 },
@@ -631,7 +601,6 @@ static const struct omap_dss_features omap2_dss_features = {
.supported_outputs = omap2_dss_supported_outputs,
.supported_color_modes = omap2_dss_supported_color_modes,
.overlay_caps = omap2_dss_overlay_caps,
- .clksrc_names = omap2_dss_clk_source_names,
.dss_params = omap2_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
.buffer_size_unit = 1,
@@ -652,7 +621,6 @@ static const struct omap_dss_features omap3430_dss_features = {
.supported_outputs = omap3430_dss_supported_outputs,
.supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3430_dss_overlay_caps,
- .clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
.buffer_size_unit = 1,
@@ -676,7 +644,6 @@ static const struct omap_dss_features am35xx_dss_features = {
.supported_outputs = omap3430_dss_supported_outputs,
.supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3430_dss_overlay_caps,
- .clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
.buffer_size_unit = 1,
@@ -696,7 +663,6 @@ static const struct omap_dss_features am43xx_dss_features = {
.supported_outputs = am43xx_dss_supported_outputs,
.supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3430_dss_overlay_caps,
- .clksrc_names = omap2_dss_clk_source_names,
.dss_params = am43xx_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA,
.buffer_size_unit = 1,
@@ -716,7 +682,6 @@ static const struct omap_dss_features omap3630_dss_features = {
.supported_outputs = omap3630_dss_supported_outputs,
.supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3630_dss_overlay_caps,
- .clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
.buffer_size_unit = 1,
@@ -738,7 +703,6 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
.supported_outputs = omap4_dss_supported_outputs,
.supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps,
- .clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
.buffer_size_unit = 16,
@@ -759,7 +723,6 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
.supported_outputs = omap4_dss_supported_outputs,
.supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps,
- .clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
.buffer_size_unit = 16,
@@ -780,7 +743,6 @@ static const struct omap_dss_features omap4_dss_features = {
.supported_outputs = omap4_dss_supported_outputs,
.supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps,
- .clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
.buffer_size_unit = 16,
@@ -801,7 +763,6 @@ static const struct omap_dss_features omap5_dss_features = {
.supported_outputs = omap5_dss_supported_outputs,
.supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps,
- .clksrc_names = omap5_dss_clk_source_names,
.dss_params = omap5_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
.buffer_size_unit = 16,
@@ -859,11 +820,6 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
color_mode;
}
-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;
diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.h b/drivers/gpu/drm/omapdrm/dss/dss_features.h
index 3d67d39f192f..bb4b7f0e642b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss_features.h
+++ b/drivers/gpu/drm/omapdrm/dss/dss_features.h
@@ -91,7 +91,6 @@ unsigned long dss_feat_get_param_max(enum dss_range_param param);
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
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 */
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index 53616b02b613..63e711545865 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -23,8 +23,9 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/hdmi.h>
-#include <video/omapdss.h>
+#include <sound/omap-hdmi-audio.h>
+#include "omapdss.h"
#include "dss.h"
/* HDMI Wrapper */
@@ -240,6 +241,7 @@ struct hdmi_pll_data {
void __iomem *base;
+ struct platform_device *pdev;
struct hdmi_wp_data *wp;
};
@@ -306,8 +308,6 @@ phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
/* HDMI PLL funcs */
void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
-void hdmi_pll_compute(struct hdmi_pll_data *pll,
- unsigned long target_tmds, struct dss_pll_clock_info *pi);
int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
struct hdmi_wp_data *wp);
void hdmi_pll_uninit(struct hdmi_pll_data *hpll);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 4d46cdf7a037..cbd28dfdb86a 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -34,9 +34,9 @@
#include <linux/regulator/consumer.h>
#include <linux/component.h>
#include <linux/of.h>
-#include <video/omapdss.h>
#include <sound/omap-hdmi-audio.h>
+#include "omapdss.h"
#include "hdmi4_core.h"
#include "dss.h"
#include "dss_features.h"
@@ -177,7 +177,11 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
if (p->double_pixel)
pc *= 2;
- hdmi_pll_compute(&hdmi.pll, pc, &hdmi_cinfo);
+ /* DSS_HDMI_TCLK is bitclk / 10 */
+ pc *= 10;
+
+ dss_pll_calc_b(&hdmi.pll.pll, clk_get_rate(hdmi.pll.pll.clkin),
+ pc, &hdmi_cinfo);
r = dss_pll_enable(&hdmi.pll.pll);
if (r) {
@@ -204,9 +208,6 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
- /* bypass TV gamma table */
- dispc_enable_gamma_table(0);
-
/* tv size */
dss_mgr_set_timings(channel, p);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index e129245eb8a9..061f9bab4c9b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -39,9 +39,9 @@
#include <linux/regulator/consumer.h>
#include <linux/component.h>
#include <linux/of.h>
-#include <video/omapdss.h>
#include <sound/omap-hdmi-audio.h>
+#include "omapdss.h"
#include "hdmi5_core.h"
#include "dss.h"
#include "dss_features.h"
@@ -190,7 +190,11 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
if (p->double_pixel)
pc *= 2;
- hdmi_pll_compute(&hdmi.pll, pc, &hdmi_cinfo);
+ /* DSS_HDMI_TCLK is bitclk / 10 */
+ pc *= 10;
+
+ dss_pll_calc_b(&hdmi.pll.pll, clk_get_rate(hdmi.pll.pll.clkin),
+ pc, &hdmi_cinfo);
/* disable and clear irqs */
hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
@@ -222,9 +226,6 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
- /* bypass TV gamma table */
- dispc_enable_gamma_table(0);
-
/* tv size */
dss_mgr_set_timings(channel, p);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_common.c b/drivers/gpu/drm/omapdrm/dss/hdmi_common.c
index 1b8fcc6c4ba1..4dfb67fe5f6d 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_common.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_common.c
@@ -4,8 +4,8 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/of.h>
-#include <video/omapdss.h>
+#include "omapdss.h"
#include "hdmi.h"
int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c b/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c
index f98b750fc499..3ead47cccac5 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c
@@ -14,8 +14,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
-#include <video/omapdss.h>
+#include "omapdss.h"
#include "dss.h"
#include "hdmi.h"
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c b/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
index f1015e8b8267..b8bf6a9e5557 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
@@ -17,9 +17,9 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/seq_file.h>
+#include <linux/pm_runtime.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#include "hdmi.h"
@@ -39,71 +39,14 @@ void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
DUMPPLL(PLLCTRL_CFG4);
}
-void hdmi_pll_compute(struct hdmi_pll_data *pll,
- unsigned long target_tmds, struct dss_pll_clock_info *pi)
-{
- unsigned long fint, clkdco, clkout;
- unsigned long target_bitclk, target_clkdco;
- unsigned long min_dco;
- unsigned n, m, mf, m2, sd;
- unsigned long clkin;
- const struct dss_pll_hw *hw = pll->pll.hw;
-
- clkin = clk_get_rate(pll->pll.clkin);
-
- DSSDBG("clkin %lu, target tmds %lu\n", clkin, target_tmds);
-
- target_bitclk = target_tmds * 10;
-
- /* Fint */
- n = DIV_ROUND_UP(clkin, hw->fint_max);
- fint = clkin / n;
-
- /* adjust m2 so that the clkdco will be high enough */
- min_dco = roundup(hw->clkdco_min, fint);
- m2 = DIV_ROUND_UP(min_dco, target_bitclk);
- if (m2 == 0)
- m2 = 1;
-
- target_clkdco = target_bitclk * m2;
- m = target_clkdco / fint;
-
- clkdco = fint * m;
-
- /* adjust clkdco with fractional mf */
- if (WARN_ON(target_clkdco - clkdco > fint))
- mf = 0;
- else
- mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
-
- if (mf > 0)
- clkdco += (u32)div_u64((u64)mf * fint, 262144);
-
- clkout = clkdco / m2;
-
- /* sigma-delta */
- sd = DIV_ROUND_UP(fint * m, 250000000);
-
- DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
- n, m, mf, m2, sd);
- DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
-
- pi->n = n;
- pi->m = m;
- pi->mf = mf;
- pi->mX[0] = m2;
- pi->sd = sd;
-
- pi->fint = fint;
- pi->clkdco = clkdco;
- pi->clkout[0] = clkout;
-}
-
static int hdmi_pll_enable(struct dss_pll *dsspll)
{
struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
struct hdmi_wp_data *wp = pll->wp;
- u16 r = 0;
+ int r;
+
+ r = pm_runtime_get_sync(&pll->pdev->dev);
+ WARN_ON(r < 0);
dss_ctrl_pll_enable(DSS_PLL_HDMI, true);
@@ -118,10 +61,14 @@ static void hdmi_pll_disable(struct dss_pll *dsspll)
{
struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
struct hdmi_wp_data *wp = pll->wp;
+ int r;
hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
dss_ctrl_pll_enable(DSS_PLL_HDMI, false);
+
+ r = pm_runtime_put_sync(&pll->pdev->dev);
+ WARN_ON(r < 0 && r != -ENOSYS);
}
static const struct dss_pll_ops dsi_pll_ops = {
@@ -131,6 +78,8 @@ static const struct dss_pll_ops dsi_pll_ops = {
};
static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
+ .type = DSS_PLL_TYPE_B,
+
.n_max = 255,
.m_min = 20,
.m_max = 4095,
@@ -154,6 +103,8 @@ static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
};
static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
+ .type = DSS_PLL_TYPE_B,
+
.n_max = 255,
.m_min = 20,
.m_max = 2045,
@@ -225,6 +176,7 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
int r;
struct resource *res;
+ pll->pdev = pdev;
pll->wp = wp;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
index 055f62fca5dc..203694a52d18 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
@@ -15,8 +15,8 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
-#include <video/omapdss.h>
+#include "omapdss.h"
#include "dss.h"
#include "hdmi.h"
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index d7e7c909bbc2..6eaf1adbd606 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -18,7 +18,872 @@
#ifndef __OMAP_DRM_DSS_H
#define __OMAP_DRM_DSS_H
-#include <video/omapdss.h>
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <video/videomode.h>
+#include <linux/platform_data/omapdss.h>
+#include <uapi/drm/drm_mode.h>
+
+#define DISPC_IRQ_FRAMEDONE (1 << 0)
+#define DISPC_IRQ_VSYNC (1 << 1)
+#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
+#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
+#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
+#define DISPC_IRQ_GFX_END_WIN (1 << 7)
+#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
+#define DISPC_IRQ_OCP_ERR (1 << 9)
+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
+#define DISPC_IRQ_VID1_END_WIN (1 << 11)
+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
+#define DISPC_IRQ_VID2_END_WIN (1 << 13)
+#define DISPC_IRQ_SYNC_LOST (1 << 14)
+#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
+#define DISPC_IRQ_WAKEUP (1 << 16)
+#define DISPC_IRQ_SYNC_LOST2 (1 << 17)
+#define DISPC_IRQ_VSYNC2 (1 << 18)
+#define DISPC_IRQ_VID3_END_WIN (1 << 19)
+#define DISPC_IRQ_VID3_FIFO_UNDERFLOW (1 << 20)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT2 (1 << 21)
+#define DISPC_IRQ_FRAMEDONE2 (1 << 22)
+#define DISPC_IRQ_FRAMEDONEWB (1 << 23)
+#define DISPC_IRQ_FRAMEDONETV (1 << 24)
+#define DISPC_IRQ_WBBUFFEROVERFLOW (1 << 25)
+#define DISPC_IRQ_WBUNCOMPLETEERROR (1 << 26)
+#define DISPC_IRQ_SYNC_LOST3 (1 << 27)
+#define DISPC_IRQ_VSYNC3 (1 << 28)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT3 (1 << 29)
+#define DISPC_IRQ_FRAMEDONE3 (1 << 30)
+
+struct omap_dss_device;
+struct omap_overlay_manager;
+struct dss_lcd_mgr_config;
+struct snd_aes_iec958;
+struct snd_cea_861_aud_if;
+struct hdmi_avi_infoframe;
+
+enum omap_display_type {
+ OMAP_DISPLAY_TYPE_NONE = 0,
+ OMAP_DISPLAY_TYPE_DPI = 1 << 0,
+ OMAP_DISPLAY_TYPE_DBI = 1 << 1,
+ OMAP_DISPLAY_TYPE_SDI = 1 << 2,
+ OMAP_DISPLAY_TYPE_DSI = 1 << 3,
+ OMAP_DISPLAY_TYPE_VENC = 1 << 4,
+ OMAP_DISPLAY_TYPE_HDMI = 1 << 5,
+ OMAP_DISPLAY_TYPE_DVI = 1 << 6,
+};
+
+enum omap_plane {
+ OMAP_DSS_GFX = 0,
+ OMAP_DSS_VIDEO1 = 1,
+ OMAP_DSS_VIDEO2 = 2,
+ OMAP_DSS_VIDEO3 = 3,
+ OMAP_DSS_WB = 4,
+};
+
+enum omap_channel {
+ OMAP_DSS_CHANNEL_LCD = 0,
+ OMAP_DSS_CHANNEL_DIGIT = 1,
+ OMAP_DSS_CHANNEL_LCD2 = 2,
+ OMAP_DSS_CHANNEL_LCD3 = 3,
+ OMAP_DSS_CHANNEL_WB = 4,
+};
+
+enum omap_color_mode {
+ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
+ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
+ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
+ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
+ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */
+ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
+ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
+ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
+ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
+ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
+ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
+ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
+ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
+ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
+ OMAP_DSS_COLOR_NV12 = 1 << 14, /* NV12 format: YUV 4:2:0 */
+ OMAP_DSS_COLOR_RGBA16 = 1 << 15, /* RGBA16 - 4444 */
+ OMAP_DSS_COLOR_RGBX16 = 1 << 16, /* RGBx16 - 4444 */
+ OMAP_DSS_COLOR_ARGB16_1555 = 1 << 17, /* ARGB16 - 1555 */
+ OMAP_DSS_COLOR_XRGB16_1555 = 1 << 18, /* xRGB16 - 1555 */
+};
+
+enum omap_dss_load_mode {
+ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
+ OMAP_DSS_LOAD_CLUT_ONLY = 1,
+ OMAP_DSS_LOAD_FRAME_ONLY = 2,
+ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
+};
+
+enum omap_dss_trans_key_type {
+ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
+ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
+};
+
+enum omap_rfbi_te_mode {
+ OMAP_DSS_RFBI_TE_MODE_1 = 1,
+ OMAP_DSS_RFBI_TE_MODE_2 = 2,
+};
+
+enum omap_dss_signal_level {
+ OMAPDSS_SIG_ACTIVE_LOW,
+ OMAPDSS_SIG_ACTIVE_HIGH,
+};
+
+enum omap_dss_signal_edge {
+ OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+ OMAPDSS_DRIVE_SIG_RISING_EDGE,
+};
+
+enum omap_dss_venc_type {
+ OMAP_DSS_VENC_TYPE_COMPOSITE,
+ OMAP_DSS_VENC_TYPE_SVIDEO,
+};
+
+enum omap_dss_dsi_pixel_format {
+ OMAP_DSS_DSI_FMT_RGB888,
+ OMAP_DSS_DSI_FMT_RGB666,
+ OMAP_DSS_DSI_FMT_RGB666_PACKED,
+ OMAP_DSS_DSI_FMT_RGB565,
+};
+
+enum omap_dss_dsi_mode {
+ OMAP_DSS_DSI_CMD_MODE = 0,
+ OMAP_DSS_DSI_VIDEO_MODE,
+};
+
+enum omap_display_caps {
+ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
+ OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1,
+};
+
+enum omap_dss_display_state {
+ OMAP_DSS_DISPLAY_DISABLED = 0,
+ OMAP_DSS_DISPLAY_ACTIVE,
+};
+
+enum omap_dss_rotation_type {
+ OMAP_DSS_ROT_DMA = 1 << 0,
+ OMAP_DSS_ROT_VRFB = 1 << 1,
+ OMAP_DSS_ROT_TILER = 1 << 2,
+};
+
+/* clockwise rotation angle */
+enum omap_dss_rotation_angle {
+ OMAP_DSS_ROT_0 = 0,
+ OMAP_DSS_ROT_90 = 1,
+ OMAP_DSS_ROT_180 = 2,
+ OMAP_DSS_ROT_270 = 3,
+};
+
+enum omap_overlay_caps {
+ OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
+ OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1,
+ OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2,
+ OMAP_DSS_OVL_CAP_ZORDER = 1 << 3,
+ OMAP_DSS_OVL_CAP_POS = 1 << 4,
+ OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5,
+};
+
+enum omap_overlay_manager_caps {
+ OMAP_DSS_DUMMY_VALUE, /* add a dummy value to prevent compiler error */
+};
+
+enum omap_dss_clk_source {
+ OMAP_DSS_CLK_SRC_FCK = 0, /* OMAP2/3: DSS1_ALWON_FCLK
+ * OMAP4: DSS_FCLK */
+ OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK
+ * OMAP4: PLL1_CLK1 */
+ OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK
+ * OMAP4: PLL1_CLK2 */
+ OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC, /* OMAP4: PLL2_CLK1 */
+ OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */
+};
+
+enum omap_hdmi_flags {
+ OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0,
+};
+
+enum omap_dss_output_id {
+ OMAP_DSS_OUTPUT_DPI = 1 << 0,
+ OMAP_DSS_OUTPUT_DBI = 1 << 1,
+ OMAP_DSS_OUTPUT_SDI = 1 << 2,
+ OMAP_DSS_OUTPUT_DSI1 = 1 << 3,
+ OMAP_DSS_OUTPUT_DSI2 = 1 << 4,
+ OMAP_DSS_OUTPUT_VENC = 1 << 5,
+ OMAP_DSS_OUTPUT_HDMI = 1 << 6,
+};
+
+/* RFBI */
+
+struct rfbi_timings {
+ int cs_on_time;
+ int cs_off_time;
+ int we_on_time;
+ int we_off_time;
+ int re_on_time;
+ int re_off_time;
+ int we_cycle_time;
+ int re_cycle_time;
+ int cs_pulse_width;
+ int access_time;
+
+ int clk_div;
+
+ u32 tim[5]; /* set by rfbi_convert_timings() */
+
+ int converted;
+};
+
+/* DSI */
+
+enum omap_dss_dsi_trans_mode {
+ /* Sync Pulses: both sync start and end packets sent */
+ OMAP_DSS_DSI_PULSE_MODE,
+ /* Sync Events: only sync start packets sent */
+ OMAP_DSS_DSI_EVENT_MODE,
+ /* Burst: only sync start packets sent, pixels are time compressed */
+ OMAP_DSS_DSI_BURST_MODE,
+};
+
+struct omap_dss_dsi_videomode_timings {
+ unsigned long hsclk;
+
+ unsigned ndl;
+ unsigned bitspp;
+
+ /* pixels */
+ u16 hact;
+ /* lines */
+ u16 vact;
+
+ /* DSI video mode blanking data */
+ /* Unit: byte clock cycles */
+ u16 hss;
+ u16 hsa;
+ u16 hse;
+ u16 hfp;
+ u16 hbp;
+ /* Unit: line clocks */
+ u16 vsa;
+ u16 vfp;
+ u16 vbp;
+
+ /* DSI blanking modes */
+ int blanking_mode;
+ int hsa_blanking_mode;
+ int hbp_blanking_mode;
+ int hfp_blanking_mode;
+
+ enum omap_dss_dsi_trans_mode trans_mode;
+
+ bool ddr_clk_always_on;
+ int window_sync;
+};
+
+struct omap_dss_dsi_config {
+ enum omap_dss_dsi_mode mode;
+ enum omap_dss_dsi_pixel_format pixel_format;
+ const struct omap_video_timings *timings;
+
+ unsigned long hs_clk_min, hs_clk_max;
+ unsigned long lp_clk_min, lp_clk_max;
+
+ bool ddr_clk_always_on;
+ enum omap_dss_dsi_trans_mode trans_mode;
+};
+
+struct omap_video_timings {
+ /* Unit: pixels */
+ u16 x_res;
+ /* Unit: pixels */
+ u16 y_res;
+ /* Unit: Hz */
+ u32 pixelclock;
+ /* Unit: pixel clocks */
+ u16 hsw; /* Horizontal synchronization pulse width */
+ /* Unit: pixel clocks */
+ u16 hfp; /* Horizontal front porch */
+ /* Unit: pixel clocks */
+ u16 hbp; /* Horizontal back porch */
+ /* Unit: line clocks */
+ u16 vsw; /* Vertical synchronization pulse width */
+ /* Unit: line clocks */
+ u16 vfp; /* Vertical front porch */
+ /* Unit: line clocks */
+ u16 vbp; /* Vertical back porch */
+
+ /* Vsync logic level */
+ enum omap_dss_signal_level vsync_level;
+ /* Hsync logic level */
+ enum omap_dss_signal_level hsync_level;
+ /* Interlaced or Progressive timings */
+ bool interlace;
+ /* Pixel clock edge to drive LCD data */
+ enum omap_dss_signal_edge data_pclk_edge;
+ /* Data enable logic level */
+ enum omap_dss_signal_level de_level;
+ /* Pixel clock edges to drive HSYNC and VSYNC signals */
+ enum omap_dss_signal_edge sync_pclk_edge;
+
+ bool double_pixel;
+};
+
+/* Hardcoded timings for tv modes. Venc only uses these to
+ * identify the mode, and does not actually use the configs
+ * itself. However, the configs should be something that
+ * a normal monitor can also show */
+extern const struct omap_video_timings omap_dss_pal_timings;
+extern const struct omap_video_timings omap_dss_ntsc_timings;
+
+struct omap_dss_cpr_coefs {
+ s16 rr, rg, rb;
+ s16 gr, gg, gb;
+ s16 br, bg, bb;
+};
+
+struct omap_overlay_info {
+ dma_addr_t paddr;
+ dma_addr_t p_uv_addr; /* for NV12 format */
+ u16 screen_width;
+ u16 width;
+ u16 height;
+ enum omap_color_mode color_mode;
+ u8 rotation;
+ enum omap_dss_rotation_type rotation_type;
+ bool mirror;
+
+ u16 pos_x;
+ u16 pos_y;
+ u16 out_width; /* if 0, out_width == width */
+ u16 out_height; /* if 0, out_height == height */
+ u8 global_alpha;
+ u8 pre_mult_alpha;
+ u8 zorder;
+};
+
+struct omap_overlay {
+ struct kobject kobj;
+ struct list_head list;
+
+ /* static fields */
+ const char *name;
+ enum omap_plane id;
+ enum omap_color_mode supported_modes;
+ enum omap_overlay_caps caps;
+
+ /* dynamic fields */
+ struct omap_overlay_manager *manager;
+
+ /*
+ * The following functions do not block:
+ *
+ * is_enabled
+ * set_overlay_info
+ * get_overlay_info
+ *
+ * The rest of the functions may block and cannot be called from
+ * interrupt context
+ */
+
+ int (*enable)(struct omap_overlay *ovl);
+ int (*disable)(struct omap_overlay *ovl);
+ bool (*is_enabled)(struct omap_overlay *ovl);
+
+ int (*set_manager)(struct omap_overlay *ovl,
+ struct omap_overlay_manager *mgr);
+ int (*unset_manager)(struct omap_overlay *ovl);
+
+ int (*set_overlay_info)(struct omap_overlay *ovl,
+ struct omap_overlay_info *info);
+ void (*get_overlay_info)(struct omap_overlay *ovl,
+ struct omap_overlay_info *info);
+
+ int (*wait_for_go)(struct omap_overlay *ovl);
+
+ struct omap_dss_device *(*get_device)(struct omap_overlay *ovl);
+};
+
+struct omap_overlay_manager_info {
+ u32 default_color;
+
+ enum omap_dss_trans_key_type trans_key_type;
+ u32 trans_key;
+ bool trans_enabled;
+
+ bool partial_alpha_enabled;
+
+ bool cpr_enable;
+ struct omap_dss_cpr_coefs cpr_coefs;
+};
+
+struct omap_overlay_manager {
+ struct kobject kobj;
+
+ /* static fields */
+ const char *name;
+ enum omap_channel id;
+ enum omap_overlay_manager_caps caps;
+ struct list_head overlays;
+ enum omap_display_type supported_displays;
+ enum omap_dss_output_id supported_outputs;
+
+ /* dynamic fields */
+ struct omap_dss_device *output;
+
+ /*
+ * The following functions do not block:
+ *
+ * set_manager_info
+ * get_manager_info
+ * apply
+ *
+ * The rest of the functions may block and cannot be called from
+ * interrupt context
+ */
+
+ int (*set_output)(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *output);
+ int (*unset_output)(struct omap_overlay_manager *mgr);
+
+ int (*set_manager_info)(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info);
+ void (*get_manager_info)(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info);
+
+ int (*apply)(struct omap_overlay_manager *mgr);
+ int (*wait_for_go)(struct omap_overlay_manager *mgr);
+ int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
+
+ struct omap_dss_device *(*get_device)(struct omap_overlay_manager *mgr);
+};
+
+/* 22 pins means 1 clk lane and 10 data lanes */
+#define OMAP_DSS_MAX_DSI_PINS 22
+
+struct omap_dsi_pin_config {
+ int num_pins;
+ /*
+ * pin numbers in the following order:
+ * clk+, clk-
+ * data1+, data1-
+ * data2+, data2-
+ * ...
+ */
+ int pins[OMAP_DSS_MAX_DSI_PINS];
+};
+
+struct omap_dss_writeback_info {
+ u32 paddr;
+ u32 p_uv_addr;
+ u16 buf_width;
+ u16 width;
+ u16 height;
+ enum omap_color_mode color_mode;
+ u8 rotation;
+ enum omap_dss_rotation_type rotation_type;
+ bool mirror;
+ u8 pre_mult_alpha;
+};
+
+struct omapdss_dpi_ops {
+ int (*connect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+ void (*disconnect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+
+ int (*enable)(struct omap_dss_device *dssdev);
+ void (*disable)(struct omap_dss_device *dssdev);
+
+ int (*check_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*set_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*get_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+
+ void (*set_data_lines)(struct omap_dss_device *dssdev, int data_lines);
+};
+
+struct omapdss_sdi_ops {
+ int (*connect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+ void (*disconnect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+
+ int (*enable)(struct omap_dss_device *dssdev);
+ void (*disable)(struct omap_dss_device *dssdev);
+
+ int (*check_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*set_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*get_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+
+ void (*set_datapairs)(struct omap_dss_device *dssdev, int datapairs);
+};
+
+struct omapdss_dvi_ops {
+ int (*connect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+ void (*disconnect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+
+ int (*enable)(struct omap_dss_device *dssdev);
+ void (*disable)(struct omap_dss_device *dssdev);
+
+ int (*check_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*set_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*get_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+};
+
+struct omapdss_atv_ops {
+ int (*connect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+ void (*disconnect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+
+ int (*enable)(struct omap_dss_device *dssdev);
+ void (*disable)(struct omap_dss_device *dssdev);
+
+ int (*check_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*set_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*get_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+
+ void (*set_type)(struct omap_dss_device *dssdev,
+ enum omap_dss_venc_type type);
+ void (*invert_vid_out_polarity)(struct omap_dss_device *dssdev,
+ bool invert_polarity);
+
+ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
+ u32 (*get_wss)(struct omap_dss_device *dssdev);
+};
+
+struct omapdss_hdmi_ops {
+ int (*connect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+ void (*disconnect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+
+ int (*enable)(struct omap_dss_device *dssdev);
+ void (*disable)(struct omap_dss_device *dssdev);
+
+ int (*check_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*set_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*get_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+
+ int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+ bool (*detect)(struct omap_dss_device *dssdev);
+
+ int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
+ int (*set_infoframe)(struct omap_dss_device *dssdev,
+ const struct hdmi_avi_infoframe *avi);
+};
+
+struct omapdss_dsi_ops {
+ int (*connect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+ void (*disconnect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+
+ int (*enable)(struct omap_dss_device *dssdev);
+ void (*disable)(struct omap_dss_device *dssdev, bool disconnect_lanes,
+ bool enter_ulps);
+
+ /* bus configuration */
+ int (*set_config)(struct omap_dss_device *dssdev,
+ const struct omap_dss_dsi_config *cfg);
+ int (*configure_pins)(struct omap_dss_device *dssdev,
+ const struct omap_dsi_pin_config *pin_cfg);
+
+ void (*enable_hs)(struct omap_dss_device *dssdev, int channel,
+ bool enable);
+ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
+
+ int (*update)(struct omap_dss_device *dssdev, int channel,
+ void (*callback)(int, void *), void *data);
+
+ void (*bus_lock)(struct omap_dss_device *dssdev);
+ void (*bus_unlock)(struct omap_dss_device *dssdev);
+
+ int (*enable_video_output)(struct omap_dss_device *dssdev, int channel);
+ void (*disable_video_output)(struct omap_dss_device *dssdev,
+ int channel);
+
+ int (*request_vc)(struct omap_dss_device *dssdev, int *channel);
+ int (*set_vc_id)(struct omap_dss_device *dssdev, int channel,
+ int vc_id);
+ void (*release_vc)(struct omap_dss_device *dssdev, int channel);
+
+ /* data transfer */
+ int (*dcs_write)(struct omap_dss_device *dssdev, int channel,
+ u8 *data, int len);
+ int (*dcs_write_nosync)(struct omap_dss_device *dssdev, int channel,
+ u8 *data, int len);
+ int (*dcs_read)(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
+ u8 *data, int len);
+
+ int (*gen_write)(struct omap_dss_device *dssdev, int channel,
+ u8 *data, int len);
+ int (*gen_write_nosync)(struct omap_dss_device *dssdev, int channel,
+ u8 *data, int len);
+ int (*gen_read)(struct omap_dss_device *dssdev, int channel,
+ u8 *reqdata, int reqlen,
+ u8 *data, int len);
+
+ int (*bta_sync)(struct omap_dss_device *dssdev, int channel);
+
+ int (*set_max_rx_packet_size)(struct omap_dss_device *dssdev,
+ int channel, u16 plen);
+};
+
+struct omap_dss_device {
+ struct kobject kobj;
+ struct device *dev;
+
+ struct module *owner;
+
+ struct list_head panel_list;
+
+ /* alias in the form of "display%d" */
+ char alias[16];
+
+ enum omap_display_type type;
+ enum omap_display_type output_type;
+
+ union {
+ struct {
+ u8 data_lines;
+ } dpi;
+
+ struct {
+ u8 channel;
+ u8 data_lines;
+ } rfbi;
+
+ struct {
+ u8 datapairs;
+ } sdi;
+
+ struct {
+ int module;
+ } dsi;
+
+ struct {
+ enum omap_dss_venc_type type;
+ bool invert_polarity;
+ } venc;
+ } phy;
+
+ struct {
+ struct omap_video_timings timings;
+
+ enum omap_dss_dsi_pixel_format dsi_pix_fmt;
+ enum omap_dss_dsi_mode dsi_mode;
+ } panel;
+
+ struct {
+ u8 pixel_size;
+ struct rfbi_timings rfbi_timings;
+ } ctrl;
+
+ const char *name;
+
+ /* used to match device to driver */
+ const char *driver_name;
+
+ void *data;
+
+ struct omap_dss_driver *driver;
+
+ union {
+ const struct omapdss_dpi_ops *dpi;
+ const struct omapdss_sdi_ops *sdi;
+ const struct omapdss_dvi_ops *dvi;
+ const struct omapdss_hdmi_ops *hdmi;
+ const struct omapdss_atv_ops *atv;
+ const struct omapdss_dsi_ops *dsi;
+ } ops;
+
+ /* helper variable for driver suspend/resume */
+ bool activate_after_resume;
+
+ enum omap_display_caps caps;
+
+ struct omap_dss_device *src;
+
+ enum omap_dss_display_state state;
+
+ /* OMAP DSS output specific fields */
+
+ struct list_head list;
+
+ /* DISPC channel for this output */
+ enum omap_channel dispc_channel;
+ bool dispc_channel_connected;
+
+ /* output instance */
+ enum omap_dss_output_id id;
+
+ /* the port number in the DT node */
+ int port_num;
+
+ /* dynamic fields */
+ struct omap_overlay_manager *manager;
+
+ struct omap_dss_device *dst;
+};
+
+struct omap_dss_driver {
+ int (*probe)(struct omap_dss_device *);
+ void (*remove)(struct omap_dss_device *);
+
+ int (*connect)(struct omap_dss_device *dssdev);
+ void (*disconnect)(struct omap_dss_device *dssdev);
+
+ int (*enable)(struct omap_dss_device *display);
+ void (*disable)(struct omap_dss_device *display);
+ int (*run_test)(struct omap_dss_device *display, int test);
+
+ int (*update)(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h);
+ int (*sync)(struct omap_dss_device *dssdev);
+
+ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
+ int (*get_te)(struct omap_dss_device *dssdev);
+
+ u8 (*get_rotate)(struct omap_dss_device *dssdev);
+ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
+
+ bool (*get_mirror)(struct omap_dss_device *dssdev);
+ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
+
+ int (*memory_read)(struct omap_dss_device *dssdev,
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h);
+
+ void (*get_resolution)(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres);
+ void (*get_dimensions)(struct omap_dss_device *dssdev,
+ u32 *width, u32 *height);
+ int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
+
+ int (*check_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*set_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*get_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+
+ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
+ u32 (*get_wss)(struct omap_dss_device *dssdev);
+
+ int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+ bool (*detect)(struct omap_dss_device *dssdev);
+
+ int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
+ int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev,
+ const struct hdmi_avi_infoframe *avi);
+};
+
+enum omapdss_version omapdss_get_version(void);
+bool omapdss_is_initialized(void);
+
+int omap_dss_register_driver(struct omap_dss_driver *);
+void omap_dss_unregister_driver(struct omap_dss_driver *);
+
+int omapdss_register_display(struct omap_dss_device *dssdev);
+void omapdss_unregister_display(struct omap_dss_device *dssdev);
+
+struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev);
+void omap_dss_put_device(struct omap_dss_device *dssdev);
+#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
+struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
+struct omap_dss_device *omap_dss_find_device(void *data,
+ int (*match)(struct omap_dss_device *dssdev, void *data));
+const char *omapdss_get_default_display_name(void);
+
+void videomode_to_omap_video_timings(const struct videomode *vm,
+ struct omap_video_timings *ovt);
+void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
+ struct videomode *vm);
+
+int dss_feat_get_num_mgrs(void);
+int dss_feat_get_num_ovls(void);
+enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
+
+
+
+int omap_dss_get_num_overlay_managers(void);
+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
+
+int omap_dss_get_num_overlays(void);
+struct omap_overlay *omap_dss_get_overlay(int num);
+
+int omapdss_register_output(struct omap_dss_device *output);
+void omapdss_unregister_output(struct omap_dss_device *output);
+struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id);
+struct omap_dss_device *omap_dss_find_output(const char *name);
+struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port);
+int omapdss_output_set_device(struct omap_dss_device *out,
+ struct omap_dss_device *dssdev);
+int omapdss_output_unset_device(struct omap_dss_device *out);
+
+struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev);
+struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev);
+
+void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres);
+int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
+void omapdss_default_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+
+typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
+
+int omapdss_compat_init(void);
+void omapdss_compat_uninit(void);
+
+static inline bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
+{
+ return dssdev->src;
+}
+
+static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev)
+{
+ return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
+}
+
+struct device_node *
+omapdss_of_get_next_port(const struct device_node *parent,
+ struct device_node *prev);
+
+struct device_node *
+omapdss_of_get_next_endpoint(const struct device_node *parent,
+ struct device_node *prev);
+
+struct device_node *
+omapdss_of_get_first_endpoint(const struct device_node *parent);
+
+struct omap_dss_device *
+omapdss_of_find_source_for_first_ep(struct device_node *node);
u32 dispc_read_irqstatus(void);
void dispc_clear_irqstatus(u32 mask);
@@ -44,6 +909,10 @@ void dispc_mgr_set_timings(enum omap_channel channel,
const struct omap_video_timings *timings);
void dispc_mgr_setup(enum omap_channel channel,
const struct omap_overlay_manager_info *info);
+u32 dispc_mgr_gamma_size(enum omap_channel channel);
+void dispc_mgr_set_gamma(enum omap_channel channel,
+ const struct drm_color_lut *lut,
+ unsigned int length);
int dispc_ovl_enable(enum omap_plane plane, bool enable);
bool dispc_ovl_enabled(enum omap_plane plane);
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index 829232ad8c81..24f859488201 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -21,8 +21,7 @@
#include <linux/slab.h>
#include <linux/of.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
static LIST_HEAD(output_list);
diff --git a/drivers/gpu/drm/omapdrm/dss/pll.c b/drivers/gpu/drm/omapdrm/dss/pll.c
index f974ddcd3b6e..0a76c89cdc2e 100644
--- a/drivers/gpu/drm/omapdrm/dss/pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/pll.c
@@ -22,8 +22,7 @@
#include <linux/regulator/consumer.h>
#include <linux/sched.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#define PLL_CONTROL 0x0000
@@ -76,6 +75,59 @@ struct dss_pll *dss_pll_find(const char *name)
return NULL;
}
+struct dss_pll *dss_pll_find_by_src(enum dss_clk_source src)
+{
+ struct dss_pll *pll;
+
+ switch (src) {
+ default:
+ case DSS_CLK_SRC_FCK:
+ return NULL;
+
+ case DSS_CLK_SRC_HDMI_PLL:
+ return dss_pll_find("hdmi");
+
+ case DSS_CLK_SRC_PLL1_1:
+ case DSS_CLK_SRC_PLL1_2:
+ case DSS_CLK_SRC_PLL1_3:
+ pll = dss_pll_find("dsi0");
+ if (!pll)
+ pll = dss_pll_find("video0");
+ return pll;
+
+ case DSS_CLK_SRC_PLL2_1:
+ case DSS_CLK_SRC_PLL2_2:
+ case DSS_CLK_SRC_PLL2_3:
+ pll = dss_pll_find("dsi1");
+ if (!pll)
+ pll = dss_pll_find("video1");
+ return pll;
+ }
+}
+
+unsigned dss_pll_get_clkout_idx_for_src(enum dss_clk_source src)
+{
+ switch (src) {
+ case DSS_CLK_SRC_HDMI_PLL:
+ return 0;
+
+ case DSS_CLK_SRC_PLL1_1:
+ case DSS_CLK_SRC_PLL2_1:
+ return 0;
+
+ case DSS_CLK_SRC_PLL1_2:
+ case DSS_CLK_SRC_PLL2_2:
+ return 1;
+
+ case DSS_CLK_SRC_PLL1_3:
+ case DSS_CLK_SRC_PLL2_3:
+ return 2;
+
+ default:
+ return 0;
+ }
+}
+
int dss_pll_enable(struct dss_pll *pll)
{
int r;
@@ -129,7 +181,7 @@ int dss_pll_set_config(struct dss_pll *pll, const struct dss_pll_clock_info *cin
return 0;
}
-bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
+bool dss_pll_hsdiv_calc_a(const struct dss_pll *pll, unsigned long clkdco,
unsigned long out_min, unsigned long out_max,
dss_hsdiv_calc_func func, void *data)
{
@@ -154,7 +206,11 @@ bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
return false;
}
-bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
+/*
+ * clkdco = clkin / n * m * 2
+ * clkoutX = clkdco / mX
+ */
+bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
unsigned long pll_min, unsigned long pll_max,
dss_pll_calc_func func, void *data)
{
@@ -195,6 +251,71 @@ bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
return false;
}
+/*
+ * This calculates a PLL config that will provide the target_clkout rate
+ * for clkout. Additionally clkdco rate will be the same as clkout rate
+ * when clkout rate is >= min_clkdco.
+ *
+ * clkdco = clkin / n * m + clkin / n * mf / 262144
+ * clkout = clkdco / m2
+ */
+bool dss_pll_calc_b(const struct dss_pll *pll, unsigned long clkin,
+ unsigned long target_clkout, struct dss_pll_clock_info *cinfo)
+{
+ unsigned long fint, clkdco, clkout;
+ unsigned long target_clkdco;
+ unsigned long min_dco;
+ unsigned n, m, mf, m2, sd;
+ const struct dss_pll_hw *hw = pll->hw;
+
+ DSSDBG("clkin %lu, target clkout %lu\n", clkin, target_clkout);
+
+ /* Fint */
+ n = DIV_ROUND_UP(clkin, hw->fint_max);
+ fint = clkin / n;
+
+ /* adjust m2 so that the clkdco will be high enough */
+ min_dco = roundup(hw->clkdco_min, fint);
+ m2 = DIV_ROUND_UP(min_dco, target_clkout);
+ if (m2 == 0)
+ m2 = 1;
+
+ target_clkdco = target_clkout * m2;
+ m = target_clkdco / fint;
+
+ clkdco = fint * m;
+
+ /* adjust clkdco with fractional mf */
+ if (WARN_ON(target_clkdco - clkdco > fint))
+ mf = 0;
+ else
+ mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
+
+ if (mf > 0)
+ clkdco += (u32)div_u64((u64)mf * fint, 262144);
+
+ clkout = clkdco / m2;
+
+ /* sigma-delta */
+ sd = DIV_ROUND_UP(fint * m, 250000000);
+
+ DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
+ n, m, mf, m2, sd);
+ DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
+
+ cinfo->n = n;
+ cinfo->m = m;
+ cinfo->mf = mf;
+ cinfo->mX[0] = m2;
+ cinfo->sd = sd;
+
+ cinfo->fint = fint;
+ cinfo->clkdco = clkdco;
+ cinfo->clkout[0] = clkout;
+
+ return true;
+}
+
static int wait_for_bit_change(void __iomem *reg, int bitnum, int value)
{
unsigned long timeout;
diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c
index 3796576dfadf..cd53566d75eb 100644
--- a/drivers/gpu/drm/omapdrm/dss/rfbi.c
+++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c
@@ -38,7 +38,7 @@
#include <linux/pm_runtime.h>
#include <linux/component.h>
-#include <video/omapdss.h>
+#include "omapdss.h"
#include "dss.h"
struct rfbi_reg { u16 idx; };
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index cd6d3bfb041d..0a96c321ce62 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -29,7 +29,7 @@
#include <linux/of.h>
#include <linux/component.h>
-#include <video/omapdss.h>
+#include "omapdss.h"
#include "dss.h"
static struct {
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index 08a2cc778ba9..6eedf2118708 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -37,8 +37,7 @@
#include <linux/of.h>
#include <linux/component.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
diff --git a/drivers/gpu/drm/omapdrm/dss/video-pll.c b/drivers/gpu/drm/omapdrm/dss/video-pll.c
index b1ec59e42940..7429de928d4e 100644
--- a/drivers/gpu/drm/omapdrm/dss/video-pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/video-pll.c
@@ -17,8 +17,7 @@
#include <linux/platform_device.h>
#include <linux/sched.h>
-#include <video/omapdss.h>
-
+#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
@@ -108,6 +107,8 @@ static const struct dss_pll_ops dss_pll_ops = {
};
static const struct dss_pll_hw dss_dra7_video_pll_hw = {
+ .type = DSS_PLL_TYPE_A,
+
.n_max = (1 << 8) - 1,
.m_max = (1 << 12) - 1,
.mX_max = (1 << 5) - 1,
@@ -124,6 +125,10 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = {
.mX_lsb[0] = 21,
.mX_msb[1] = 30,
.mX_lsb[1] = 26,
+ .mX_msb[2] = 4,
+ .mX_lsb[2] = 0,
+ .mX_msb[3] = 9,
+ .mX_lsb[3] = 5,
.has_refsel = true,
};