summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c132
-rw-r--r--drivers/video/omap2/dss/dsi.c240
-rw-r--r--drivers/video/omap2/dss/dss.c51
-rw-r--r--drivers/video/omap2/dss/dss_features.c9
-rw-r--r--drivers/video/omap2/dss/dss_features.h30
5 files changed, 346 insertions, 116 deletions
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 56702c5e577f..05288c90f24f 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -37,6 +37,7 @@
#include <plat/mmc.h>
#include <plat/omap4-keypad.h>
#include <plat/display.h>
+#include <plat/nokia-dsi-panel.h>
#include "mux.h"
#include "hsmmc.h"
@@ -50,6 +51,11 @@
#define OMAP4_SFH7741_ENABLE_GPIO 188
#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define LCD_BL_GPIO 27 /* LCD Backlight GPIO */
+/* PWM2 and TOGGLE3 register offsets */
+#define LED_PWM2ON 0x03
+#define LED_PWM2OFF 0x04
+#define TWL6030_TOGGLE3 0x92
static const int sdp4430_keymap[] = {
KEY(0, 0, KEY_E),
@@ -306,24 +312,13 @@ error1:
return status;
}
-static struct platform_device sdp4430_lcd_device = {
- .name = "sdp4430_lcd",
- .id = -1,
-};
-
static struct platform_device *sdp4430_devices[] __initdata = {
- &sdp4430_lcd_device,
&sdp4430_gpio_keys_device,
&sdp4430_leds_gpio,
&sdp4430_leds_pwm,
};
-static struct omap_lcd_config sdp4430_lcd_config __initdata = {
- .ctrl_name = "internal",
-};
-
static struct omap_board_config_kernel sdp4430_config[] __initdata = {
- { OMAP_TAG_LCD, &sdp4430_lcd_config },
};
static void __init omap_4430sdp_init_early(void)
@@ -378,6 +373,10 @@ static struct regulator_consumer_supply sdp4430_vmmc_supply[] = {
.dev_name = "omap_hsmmc.0",
},
};
+static struct regulator_consumer_supply sdp4430_vcxio_supply[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
static int omap4_twl6030_hsmmc_late_init(struct device *dev)
{
@@ -524,7 +523,10 @@ static struct regulator_init_data sdp4430_vcxio = {
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
+ .always_on = true,
},
+ .num_consumer_supplies = ARRAY_SIZE(sdp4430_vcxio_supply),
+ .consumer_supplies = sdp4430_vcxio_supply,
};
static struct regulator_init_data sdp4430_vdac = {
@@ -631,6 +633,73 @@ static void __init omap_sfh7741prox_init(void)
}
}
+static int dsi1_panel_set_backlight(struct omap_dss_device *dssdev, int level)
+{
+ int r;
+
+ r = twl_i2c_write_u8(TWL_MODULE_PWM, 0x7F, LED_PWM2OFF);
+ if (r)
+ return r;
+
+ if (level > 1) {
+ if (level == 255)
+ level = 0x7F;
+ else
+ level = (~(level/2)) & 0x7F;
+
+ r = twl_i2c_write_u8(TWL_MODULE_PWM, level, LED_PWM2ON);
+ if (r)
+ return r;
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x30, TWL6030_TOGGLE3);
+ if (r)
+ return r;
+ } else if (level <= 1) {
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x08, TWL6030_TOGGLE3);
+ if (r)
+ return r;
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x28, TWL6030_TOGGLE3);
+ if (r)
+ return r;
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x00, TWL6030_TOGGLE3);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static struct nokia_dsi_panel_data dsi1_panel;
+
+static void sdp4430_lcd_init(void)
+{
+ u32 reg;
+ int status;
+
+ /* Enable DSI1 Lanes */
+ reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+ reg |= OMAP4_DSI1_PIPD_MASK | OMAP4_DSI1_LANEENABLE_MASK;
+ omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+ /* Panel Taal reset and backlight GPIO init */
+ status = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT,
+ "lcd_reset_gpio");
+ if (status)
+ pr_err("%s: Could not get lcd_reset_gpio\n", __func__);
+
+ if (dsi1_panel.use_ext_te) {
+ status = omap_mux_init_signal("gpmc_ncs4.gpio_101",
+ OMAP_PIN_INPUT_PULLUP);
+ if (status)
+ pr_err("%s: Could not get ext_te gpio\n", __func__);
+ }
+
+ status = gpio_request_one(LCD_BL_GPIO, GPIOF_DIR_OUT, "lcd_bl_gpio");
+ if (status)
+ pr_err("%s: Could not get lcd_bl_gpio\n", __func__);
+
+ gpio_set_value(LCD_BL_GPIO, 0);
+}
+
static void sdp4430_hdmi_mux_init(void)
{
/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
@@ -676,6 +745,43 @@ static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
gpio_free(HDMI_GPIO_HPD);
}
+static struct nokia_dsi_panel_data dsi1_panel = {
+ .name = "taal",
+ .reset_gpio = 102,
+ .use_ext_te = false,
+ .ext_te_gpio = 101,
+ .use_esd_check = false,
+ .set_backlight = dsi1_panel_set_backlight,
+};
+
+static struct omap_dss_device sdp4430_lcd_device = {
+ .name = "lcd",
+ .driver_name = "taal",
+ .type = OMAP_DISPLAY_TYPE_DSI,
+ .data = &dsi1_panel,
+ .phy.dsi = {
+ .clk_lane = 1,
+ .clk_pol = 0,
+ .data1_lane = 2,
+ .data1_pol = 0,
+ .data2_lane = 3,
+ .data2_pol = 0,
+ .div = {
+ .regn = 16, /* Fint = 2.4 MHz */
+ .regm = 180, /* DDR Clock = 216 MHz */
+ .regm_dispc = 5, /* PLL1_CLK1 = 172.8 MHz */
+ .regm_dsi = 5, /* PLL1_CLK2 = 172.8 MHz */
+
+ .lp_clk_div = 10, /* LP Clock = 8.64 MHz */
+
+ .lck_div = 1, /* Logic Clock = 172.8 MHz */
+ .pck_div = 5, /* Pixel Clock = 34.56 MHz */
+
+ },
+ },
+ .channel = OMAP_DSS_CHANNEL_LCD,
+};
+
static struct omap_dss_device sdp4430_hdmi_device = {
.name = "hdmi",
.driver_name = "hdmi_panel",
@@ -686,17 +792,19 @@ static struct omap_dss_device sdp4430_hdmi_device = {
};
static struct omap_dss_device *sdp4430_dss_devices[] = {
+ &sdp4430_lcd_device,
&sdp4430_hdmi_device,
};
static struct omap_dss_board_info sdp4430_dss_data = {
.num_devices = ARRAY_SIZE(sdp4430_dss_devices),
.devices = sdp4430_dss_devices,
- .default_device = &sdp4430_hdmi_device,
+ .default_device = &sdp4430_lcd_device,
};
void omap_4430sdp_display_init(void)
{
+ sdp4430_lcd_init();
sdp4430_hdmi_mux_init();
omap_display_init(&sdp4430_dss_data);
}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 0a7f1a47f8e3..23d9bbe68b82 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1270,7 +1270,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
{
int r = 0;
u32 l;
- int f;
+ int f = 0;
u8 regn_start, regn_end, regm_start, regm_end;
u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
@@ -1341,19 +1341,19 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max);
- if (cinfo->fint < 1000000)
- f = 0x3;
- else if (cinfo->fint < 1250000)
- f = 0x4;
- else if (cinfo->fint < 1500000)
- f = 0x5;
- else if (cinfo->fint < 1750000)
- f = 0x6;
- else
- f = 0x7;
+
+ if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
+ f = cinfo->fint < 1000000 ? 0x3 :
+ cinfo->fint < 1250000 ? 0x4 :
+ cinfo->fint < 1500000 ? 0x5 :
+ cinfo->fint < 1750000 ? 0x6 :
+ 0x7;
+ }
l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
- l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
+
+ if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
+ l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
11, 11); /* DSI_PLL_CLKSEL */
l = FLD_MOD(l, cinfo->highfreq,
@@ -1873,9 +1873,6 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
DSSDBG("dsi_complexio_init\n");
- /* CIO_CLK_ICG, enable L3 clk to CIO */
- REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
-
/* A dummy read using the SCP interface to any DSIPHY register is
* required after DSIPHY reset to complete the reset of the DSI complex
* I/O. */
@@ -1900,10 +1897,12 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
goto err;
}
- if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
- DSSERR("ComplexIO LDO power down.\n");
- r = -ENODEV;
- goto err;
+ if (dss_has_feature(FEAT_DSI_LDO_STATUS)) {
+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
+ DSSERR("ComplexIO LDO power down.\n");
+ r = -ENODEV;
+ goto err;
+ }
}
dsi_complexio_timings();
@@ -2034,6 +2033,114 @@ static int dsi_force_tx_stop_mode_io(void)
return 0;
}
+static bool dsi_vc_is_enabled(int channel)
+{
+ return REG_GET(DSI_VC_CTRL(channel), 0, 0);
+}
+
+static void dsi_packet_sent_handler_vp(void *data, u32 mask)
+{
+ const int channel = dsi.update_channel;
+ u8 bit = dsi.te_enabled ? 30 : 31;
+
+ if (REG_GET(DSI_VC_TE(channel), bit, bit) == 0)
+ complete((struct completion *)data);
+}
+
+static int dsi_sync_vc_vp(int channel)
+{
+ int r = 0;
+ u8 bit;
+
+ DECLARE_COMPLETION_ONSTACK(completion);
+
+ bit = dsi.te_enabled ? 30 : 31;
+
+ r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_vp,
+ &completion, DSI_VC_IRQ_PACKET_SENT);
+ if (r)
+ goto err0;
+
+ /* Wait for completion only if TE_EN/TE_START is still set */
+ if (REG_GET(DSI_VC_TE(channel), bit, bit)) {
+ if (wait_for_completion_timeout(&completion,
+ msecs_to_jiffies(10)) == 0) {
+ DSSERR("Failed to complete previous frame transfer\n");
+ r = -EIO;
+ goto err1;
+ }
+ }
+
+ dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp,
+ &completion, DSI_VC_IRQ_PACKET_SENT);
+
+ return 0;
+err1:
+ dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp, &completion,
+ DSI_VC_IRQ_PACKET_SENT);
+err0:
+ return r;
+}
+
+static void dsi_packet_sent_handler_l4(void *data, u32 mask)
+{
+ const int channel = dsi.update_channel;
+
+ if (REG_GET(DSI_VC_CTRL(channel), 5, 5) == 0)
+ complete((struct completion *)data);
+}
+
+static int dsi_sync_vc_l4(int channel)
+{
+ int r = 0;
+
+ DECLARE_COMPLETION_ONSTACK(completion);
+
+ r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_l4,
+ &completion, DSI_VC_IRQ_PACKET_SENT);
+ if (r)
+ goto err0;
+
+ /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */
+ if (REG_GET(DSI_VC_CTRL(channel), 5, 5)) {
+ if (wait_for_completion_timeout(&completion,
+ msecs_to_jiffies(10)) == 0) {
+ DSSERR("Failed to complete previous l4 transfer\n");
+ r = -EIO;
+ goto err1;
+ }
+ }
+
+ dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4,
+ &completion, DSI_VC_IRQ_PACKET_SENT);
+
+ return 0;
+err1:
+ dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4,
+ &completion, DSI_VC_IRQ_PACKET_SENT);
+err0:
+ return r;
+}
+
+static int dsi_sync_vc(int channel)
+{
+ WARN_ON(!dsi_bus_is_locked());
+
+ WARN_ON(in_interrupt());
+
+ if (!dsi_vc_is_enabled(channel))
+ return 0;
+
+ switch (dsi.vc[channel].mode) {
+ case DSI_VC_MODE_VP:
+ return dsi_sync_vc_vp(channel);
+ case DSI_VC_MODE_L4:
+ return dsi_sync_vc_l4(channel);
+ default:
+ BUG();
+ }
+}
+
static int dsi_vc_enable(int channel, bool enable)
{
DSSDBG("dsi_vc_enable channel %d, enable %d\n",
@@ -2070,6 +2177,8 @@ static void dsi_vc_initial_config(int channel)
r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
+ if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
+ r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */
r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
@@ -2084,6 +2193,8 @@ static int dsi_vc_config_l4(int channel)
DSSDBGF("%d", channel);
+ dsi_sync_vc(channel);
+
dsi_vc_enable(channel, 0);
/* VC_BUSY */
@@ -2094,6 +2205,10 @@ static int dsi_vc_config_l4(int channel)
REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
+ /* DCS_CMD_ENABLE */
+ if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
+ REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 30, 30);
+
dsi_vc_enable(channel, 1);
dsi.vc[channel].mode = DSI_VC_MODE_L4;
@@ -2108,6 +2223,8 @@ static int dsi_vc_config_vp(int channel)
DSSDBGF("%d", channel);
+ dsi_sync_vc(channel);
+
dsi_vc_enable(channel, 0);
/* VC_BUSY */
@@ -2118,6 +2235,10 @@ static int dsi_vc_config_vp(int channel)
REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
+ /* DCS_CMD_ENABLE */
+ if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
+ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 30, 30);
+
dsi_vc_enable(channel, 1);
dsi.vc[channel].mode = DSI_VC_MODE_VP;
@@ -2773,8 +2894,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
- r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
- r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
+ if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
+ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
+ /* DCS_CMD_CODE, 1=start, 0=continue */
+ r = FLD_MOD(r, 0, 25, 25);
+ }
dsi_write_reg(DSI_CTRL, r);
@@ -3093,17 +3217,8 @@ static void dsi_te_timeout(unsigned long arg)
}
#endif
-static void dsi_framedone_bta_callback(void *data, u32 mask);
-
static void dsi_handle_framedone(int error)
{
- const int channel = dsi.update_channel;
-
- dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
- NULL, DSI_VC_IRQ_BTA);
-
- cancel_delayed_work(&dsi.framedone_timeout_work);
-
/* SIDLEMODE back to smart-idle */
dispc_enable_sidle();
@@ -3112,14 +3227,6 @@ static void dsi_handle_framedone(int error)
REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
}
- /* RX_FIFO_NOT_EMPTY */
- if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
- DSSERR("Received error during frame transfer:\n");
- dsi_vc_flush_receive_data(channel);
- if (!error)
- error = -EIO;
- }
-
dsi.framedone_callback(error, dsi.framedone_data);
if (!error)
@@ -3140,61 +3247,20 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
dsi_handle_framedone(-ETIMEDOUT);
}
-static void dsi_framedone_bta_callback(void *data, u32 mask)
-{
- dsi_handle_framedone(0);
-
-#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
- dispc_fake_vsync_irq();
-#endif
-}
-
static void dsi_framedone_irq_callback(void *data, u32 mask)
{
- const int channel = dsi.update_channel;
- int r;
-
/* Note: We get FRAMEDONE when DISPC has finished sending pixels and
* turns itself off. However, DSI still has the pixels in its buffers,
* and is sending the data.
*/
- if (dsi.te_enabled) {
- /* enable LP_RX_TO again after the TE */
- REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
- }
+ __cancel_delayed_work(&dsi.framedone_timeout_work);
- /* Send BTA after the frame. We need this for the TE to work, as TE
- * trigger is only sent for BTAs without preceding packet. Thus we need
- * to BTA after the pixel packets so that next BTA will cause TE
- * trigger.
- *
- * This is not needed when TE is not in use, but we do it anyway to
- * make sure that the transfer has been completed. It would be more
- * optimal, but more complex, to wait only just before starting next
- * transfer.
- *
- * Also, as there's no interrupt telling when the transfer has been
- * done and the channel could be reconfigured, the only way is to
- * busyloop until TE_SIZE is zero. With BTA we can do this
- * asynchronously.
- * */
-
- r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback,
- NULL, DSI_VC_IRQ_BTA);
- if (r) {
- DSSERR("Failed to register BTA ISR\n");
- dsi_handle_framedone(-EIO);
- return;
- }
+ dsi_handle_framedone(0);
- r = dsi_vc_send_bta(channel);
- if (r) {
- DSSERR("BTA after framedone failed\n");
- dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
- NULL, DSI_VC_IRQ_BTA);
- dsi_handle_framedone(-EIO);
- }
+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+ dispc_fake_vsync_irq();
+#endif
}
int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
@@ -3371,6 +3437,10 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
{
int r;
+ /* The SCPClk is required for both PLL and CIO registers on OMAP4 */
+ /* CIO_CLK_ICG, enable L3 clk to CIO */
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
+
_dsi_print_reset_status();
r = dsi_pll_init(dssdev, true, true);
@@ -3383,6 +3453,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI);
+ dss_select_lcd_clk_source(dssdev->manager->id,
+ DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
DSSDBG("PLL OK\n");
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 3f1fee63c678..9a73af609c01 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -68,6 +68,7 @@ static struct {
struct clk *dss_sys_clk;
struct clk *dss_tv_fck;
struct clk *dss_video_fck;
+ struct clk *dss_dss_clk;
unsigned num_clks_enabled;
unsigned long cache_req_pck;
@@ -816,6 +817,7 @@ static int dss_get_clocks(void)
dss.dss_sys_clk = NULL;
dss.dss_tv_fck = NULL;
dss.dss_video_fck = NULL;
+ dss.dss_dss_clk = NULL;
r = dss_get_clock(&dss.dss_ick, "ick");
if (r)
@@ -848,6 +850,12 @@ static int dss_get_clocks(void)
goto err;
}
+ if (pdata->opt_clock_available("dss_clk")) {
+ r = dss_get_clock(&dss.dss_dss_clk, "dss_clk");
+ if (r)
+ goto err;
+ }
+
return 0;
err:
@@ -861,7 +869,8 @@ err:
clk_put(dss.dss_tv_fck);
if (dss.dss_video_fck)
clk_put(dss.dss_video_fck);
-
+ if (dss.dss_dss_clk)
+ clk_put(dss.dss_dss_clk);
return r;
}
@@ -873,6 +882,8 @@ static void dss_put_clocks(void)
clk_put(dss.dss_tv_fck);
if (dss.dss_sys_clk)
clk_put(dss.dss_sys_clk);
+ if (dss.dss_dss_clk)
+ clk_put(dss.dss_dss_clk);
clk_put(dss.dss_fck);
clk_put(dss.dss_ick);
}
@@ -882,8 +893,16 @@ unsigned long dss_clk_get_rate(enum dss_clock clk)
switch (clk) {
case DSS_CLK_ICK:
return clk_get_rate(dss.dss_ick);
+ /*
+ * XXX: tie dss_dss_clk to FCK - this will change with following
+ * pm_runtime patches. Needed for getting the correct clock rate
+ * for DSS_CLK_FCLK on OMAP4.
+ */
case DSS_CLK_FCK:
- return clk_get_rate(dss.dss_fck);
+ if (dss.dss_dss_clk)
+ return clk_get_rate(dss.dss_dss_clk);
+ else
+ return clk_get_rate(dss.dss_fck);
case DSS_CLK_SYSCK:
return clk_get_rate(dss.dss_sys_clk);
case DSS_CLK_TVFCK:
@@ -920,8 +939,16 @@ static void dss_clk_enable_no_ctx(enum dss_clock clks)
if (clks & DSS_CLK_ICK)
clk_enable(dss.dss_ick);
- if (clks & DSS_CLK_FCK)
+ /*
+ * XXX: tie dss_dss_clk to FCK - this will change with following
+ * pm_runtime patches. Needed for OMAP4 boot up due to stricter
+ * clock cutting in pm framework post 2.6.38-rc5.
+ */
+ if (clks & DSS_CLK_FCK) {
clk_enable(dss.dss_fck);
+ if (dss.dss_dss_clk)
+ clk_enable(dss.dss_dss_clk);
+ }
if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
clk_enable(dss.dss_sys_clk);
if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
@@ -956,8 +983,16 @@ static void dss_clk_disable_no_ctx(enum dss_clock clks)
if (clks & DSS_CLK_ICK)
clk_disable(dss.dss_ick);
- if (clks & DSS_CLK_FCK)
+ /*
+ * XXX: tie dss_dss_clk to FCK - this will change with following
+ * pm_runtime patches. Needed for OMAP4 boot up due to stricter
+ * clock cutting in pm framework post 2.6.38-rc5.
+ */
+ if (clks & DSS_CLK_FCK) {
clk_disable(dss.dss_fck);
+ if (dss.dss_dss_clk)
+ clk_disable(dss.dss_dss_clk);
+ }
if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
clk_disable(dss.dss_sys_clk);
if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
@@ -1015,6 +1050,14 @@ static void core_dump_clocks(struct seq_file *s)
dss.dss_video_fck
};
+ /*
+ * XXX: tie dss_dss_clk to FCK - this will change with following
+ * pm_runtime patches. Needed for getting the correct clock rate
+ * for DSS_CLK_FCLK on OMAP4.
+ */
+ if (dss.dss_dss_clk)
+ clocks[1] = dss.dss_dss_clk;
+
seq_printf(s, "- CORE -\n");
seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index aa1622241d0d..179a7a4f63bb 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -252,7 +252,8 @@ static struct omap_dss_features omap3430_dss_features = {
FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
- FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF,
+ FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
+ FEAT_DSI_PLL_FREQSEL | FEAT_DSI_LDO_STATUS,
.num_mgrs = 2,
.num_ovls = 3,
@@ -271,7 +272,8 @@ static struct omap_dss_features omap3630_dss_features = {
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
- FEAT_RESIZECONF,
+ FEAT_RESIZECONF | FEAT_DSI_PLL_FREQSEL |
+ FEAT_DSI_LDO_STATUS,
.num_mgrs = 2,
.num_ovls = 3,
@@ -289,7 +291,8 @@ static struct omap_dss_features omap4_dss_features = {
.has_feature =
FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
- FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC,
+ FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
+ FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH,
.num_mgrs = 3,
.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 12e9c4ef0dec..c5c0b4001ab3 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -26,20 +26,24 @@
/* DSS has feature id */
enum dss_feat_id {
- FEAT_GLOBAL_ALPHA = 1 << 0,
- FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
- FEAT_PRE_MULT_ALPHA = 1 << 2,
- FEAT_LCDENABLEPOL = 1 << 3,
- FEAT_LCDENABLESIGNAL = 1 << 4,
- FEAT_PCKFREEENABLE = 1 << 5,
- FEAT_FUNCGATED = 1 << 6,
- FEAT_MGR_LCD2 = 1 << 7,
- FEAT_LINEBUFFERSPLIT = 1 << 8,
- FEAT_ROWREPEATENABLE = 1 << 9,
- FEAT_RESIZECONF = 1 << 10,
+ FEAT_GLOBAL_ALPHA = 1 << 0,
+ FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
+ FEAT_PRE_MULT_ALPHA = 1 << 2,
+ FEAT_LCDENABLEPOL = 1 << 3,
+ FEAT_LCDENABLESIGNAL = 1 << 4,
+ FEAT_PCKFREEENABLE = 1 << 5,
+ FEAT_FUNCGATED = 1 << 6,
+ FEAT_MGR_LCD2 = 1 << 7,
+ FEAT_LINEBUFFERSPLIT = 1 << 8,
+ FEAT_ROWREPEATENABLE = 1 << 9,
+ FEAT_RESIZECONF = 1 << 10,
/* Independent core clk divider */
- FEAT_CORE_CLK_DIV = 1 << 11,
- FEAT_LCD_CLK_SRC = 1 << 12,
+ FEAT_CORE_CLK_DIV = 1 << 11,
+ FEAT_LCD_CLK_SRC = 1 << 12,
+ FEAT_DSI_PLL_FREQSEL = 1 << 13,
+ FEAT_DSI_LDO_STATUS = 1 << 14,
+ FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15,
+ FEAT_DSI_VC_OCP_WIDTH = 1 << 16,
};
/* DSS register field id */