summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJimmy Rubin <jimmy.rubin@stericsson.com>2011-10-28 12:32:33 +0200
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:04:22 +0200
commita5c5d89cfaee85c040e12de7c3f8007cc76969ae (patch)
tree34f1a43e92ee677262e38bba31e9f368a6e0be62
parent8e3285064199eeb228662b59e8da14c033e0bb66 (diff)
video: mcde: Add dsi/dpi freq settings
For U8500, the clocks used by DSI is dsilp and dsihs. These clock rates of these clocks must be specified in the port struct. The lcd clk is set from the port struct. ST-Ericsson ID: 359227, 352847 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I089a736da281014902ca8d503e72a572c9ce1bbe Signed-off-by: Jimmy Rubin <jimmy.rubin@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42452 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Per PERSSON <per.xb.persson@stericsson.com>
-rw-r--r--drivers/video/mcde/display-av8100.c11
-rw-r--r--drivers/video/mcde/display-samsung_s6d16d0.c5
-rw-r--r--drivers/video/mcde/display-sony_acx424akp_dsi.c5
-rw-r--r--drivers/video/mcde/mcde_hw.c169
-rw-r--r--include/video/mcde.h4
5 files changed, 136 insertions, 58 deletions
diff --git a/drivers/video/mcde/display-av8100.c b/drivers/video/mcde/display-av8100.c
index b99fda2f34c..b5116621e16 100644
--- a/drivers/video/mcde/display-av8100.c
+++ b/drivers/video/mcde/display-av8100.c
@@ -39,6 +39,9 @@
#define NUM_FB_BUFFERS 2
#endif
+#define DSI_HS_FREQ_HZ 840320000
+#define DSI_LP_FREQ_HZ 19200000
+
struct cea_vesa_video_mode {
u32 cea;
u32 vesa_cea_nr;
@@ -1421,6 +1424,7 @@ set_power_and_exit:
static int __devinit hdmi_probe(struct mcde_display_device *dev)
{
int ret = 0;
+ struct mcde_port *port;
struct display_driver_data *driver_data;
struct mcde_display_hdmi_platform_data *pdata =
dev->dev.platform_data;
@@ -1454,7 +1458,12 @@ static int __devinit hdmi_probe(struct mcde_display_device *dev)
dev->set_pixel_format = hdmi_set_pixel_format;
dev->set_power_mode = hdmi_set_power_mode;
- dev->port->phy.dsi.host_eot_gen = true;
+ port = dev->port;
+
+ port->phy.dsi.host_eot_gen = true;
+ port->phy.dsi.num_data_lanes = 2;
+ port->phy.dsi.hs_freq = DSI_HS_FREQ_HZ;
+ port->phy.dsi.lp_freq = DSI_LP_FREQ_HZ;
/* Create sysfs files */
if (device_create_file(&dev->dev, &dev_attr_hdmisdtvswitch))
diff --git a/drivers/video/mcde/display-samsung_s6d16d0.c b/drivers/video/mcde/display-samsung_s6d16d0.c
index 2f67f3e6abf..62db3db6556 100644
--- a/drivers/video/mcde/display-samsung_s6d16d0.c
+++ b/drivers/video/mcde/display-samsung_s6d16d0.c
@@ -27,6 +27,9 @@
#define IO_REGU_MIN 1650000
#define IO_REGU_MAX 3300000
+#define DSI_HS_FREQ_HZ 420160000
+#define DSI_LP_FREQ_HZ 19200000
+
struct device_info {
int reset_gpio;
struct mcde_port port;
@@ -165,6 +168,8 @@ static int __devinit samsung_s6d16d0_probe(struct mcde_display_device *ddev)
di->port.phy.dsi.host_eot_gen = true;
/* TODO: Move UI to mcde_hw.c when clk_get_rate(dsi) is done */
di->port.phy.dsi.ui = 9;
+ di->port.phy.dsi.hs_freq = DSI_HS_FREQ_HZ;
+ di->port.phy.dsi.lp_freq = DSI_LP_FREQ_HZ;
ret = gpio_request(di->reset_gpio, NULL);
if (ret)
diff --git a/drivers/video/mcde/display-sony_acx424akp_dsi.c b/drivers/video/mcde/display-sony_acx424akp_dsi.c
index a365a42b4d2..44302de8f1b 100644
--- a/drivers/video/mcde/display-sony_acx424akp_dsi.c
+++ b/drivers/video/mcde/display-sony_acx424akp_dsi.c
@@ -29,6 +29,9 @@
#define IO_REGU_MIN 1600000
#define IO_REGU_MAX 3300000
+#define DSI_HS_FREQ_HZ 420160000
+#define DSI_LP_FREQ_HZ 19200000
+
struct device_info {
int reset_gpio;
struct mcde_port port;
@@ -259,6 +262,8 @@ static int __devinit sony_acx424akp_probe(struct mcde_display_device *dev)
di->port.phy.dsi.host_eot_gen = true;
/* TODO: Move UI to mcde_hw.c when clk_get_rate(dsi) is done */
di->port.phy.dsi.ui = 9;
+ di->port.phy.dsi.hs_freq = DSI_HS_FREQ_HZ;
+ di->port.phy.dsi.lp_freq = DSI_LP_FREQ_HZ;
ret = gpio_request(di->reset_gpio, NULL);
if (WARN_ON(ret))
diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c
index 2580252a12f..3db1d50d3c1 100644
--- a/drivers/video/mcde/mcde_hw.c
+++ b/drivers/video/mcde/mcde_hw.c
@@ -99,6 +99,7 @@ static void wait_for_flow_disabled(struct mcde_chnl_state *chnl);
#define DSI_READ_DELAY 5
#define DSI_READ_NBR_OF_RETRIES 2
#define MCDE_FLOWEN_MAX_TRIAL 60
+#define DSI_RESET_SW 0x7
#define MCDE_VERSION_4_1_3 0x04010300
#define MCDE_VERSION_4_0_4 0x04000400
@@ -106,6 +107,9 @@ static void wait_for_flow_disabled(struct mcde_chnl_state *chnl);
#define MCDE_VERSION_3_0_5 0x03000500
#define MCDE_VERSION_1_0_4 0x01000400
+#define CLK_MCDE "mcde"
+#define CLK_DPI "lcd"
+
static u8 *mcdeio;
static u8 **dsiio;
static struct platform_device *mcde_dev;
@@ -120,14 +124,17 @@ static u32 output_fifo_c0c1_size;
static struct regulator *regulator_vana;
static struct regulator *regulator_mcde_epod;
static struct regulator *regulator_esram_epod;
-static struct clk *clock_dpi;
-static struct clk *clock_dsi;
static struct clk *clock_mcde;
+
+/* TODO remove when all platforms support dsilp and dsihs clocks */
+static struct clk *clock_dsi;
static struct clk *clock_dsi_lp;
+
static u8 mcde_is_enabled;
static struct delayed_work hw_timeout_work;
static u8 dsi_pll_is_enabled;
static u8 dsi_ifc_is_supported;
+static u8 dsi_use_clk_framework;
static u32 mcde_clk_rate; /* In Hz */
static struct mutex mcde_hw_lock;
@@ -348,6 +355,10 @@ struct mcde_chnl_state {
wait_queue_head_t vcmp_waitq;
atomic_t vcmp_cnt;
struct timer_list dsi_te_timer;
+ struct clk *clk_dsi_lp;
+ struct clk *clk_dsi_hs;
+ struct clk *clk_dpi;
+
enum mcde_display_power_mode power_mode;
/* Staged settings */
@@ -414,7 +425,8 @@ static void enable_clocks_and_power(struct platform_device *pdev)
WARN_ON_ONCE(regulator_enable(regulator_mcde_epod));
- pdata->platform_set_clocks();
+ if (!dsi_use_clk_framework)
+ pdata->platform_set_clocks();
WARN_ON_ONCE(clk_enable(clock_mcde));
}
@@ -532,26 +544,32 @@ static void dsi_link_handle_ulpm(struct mcde_port *port, bool enter_ulpm)
static int dsi_link_enable(struct mcde_chnl_state *chnl)
{
+ int ret = 0;
u8 link = chnl->port.link;
- WARN_ON_ONCE(clk_enable(clock_dsi));
- WARN_ON_ONCE(clk_enable(clock_dsi_lp));
-
- if (!dsi_pll_is_enabled) {
- int ret;
- struct mcde_platform_data *pdata =
- mcde_dev->dev.platform_data;
- ret = pdata->platform_enable_dsipll();
- if (ret < 0) {
- dev_warn(&mcde_dev->dev, "%s: "
- "enable_dsipll failed ret = %d\n",
- __func__, ret);
- goto enable_dsipll_err;
+ if (dsi_use_clk_framework) {
+ prcmu_write(DB8500_PRCM_DSI_SW_RESET, DSI_RESET_SW);
+ WARN_ON_ONCE(clk_enable(chnl->clk_dsi_lp));
+ WARN_ON_ONCE(clk_enable(chnl->clk_dsi_hs));
+ } else {
+ WARN_ON_ONCE(clk_enable(clock_dsi));
+ WARN_ON_ONCE(clk_enable(clock_dsi_lp));
+
+ if (!dsi_pll_is_enabled) {
+ struct mcde_platform_data *pdata =
+ mcde_dev->dev.platform_data;
+ ret = pdata->platform_enable_dsipll();
+ if (ret < 0) {
+ dev_warn(&mcde_dev->dev, "%s: "
+ "enable_dsipll failed ret = %d\n",
+ __func__, ret);
+ goto enable_dsipll_err;
+ }
+ dev_dbg(&mcde_dev->dev, "%s enable dsipll\n",
+ __func__);
}
- dev_dbg(&mcde_dev->dev, "%s enable dsipll\n",
- __func__);
+ dsi_pll_is_enabled++;
}
- dsi_pll_is_enabled++;
dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, LINK_EN, true);
@@ -575,7 +593,7 @@ static int dsi_link_enable(struct mcde_chnl_state *chnl)
enable_dsipll_err:
clk_disable(clock_dsi_lp);
clk_disable(clock_dsi);
- return -EINVAL;
+ return ret;
}
static void dsi_link_disable(struct mcde_chnl_state *chnl, bool suspend)
@@ -584,15 +602,20 @@ static void dsi_link_disable(struct mcde_chnl_state *chnl, bool suspend)
/* only enter ULPM when device is suspended */
if (suspend)
dsi_link_handle_ulpm(&chnl->port, true);
- if (dsi_pll_is_enabled && (--dsi_pll_is_enabled == 0)) {
- struct mcde_platform_data *pdata =
- mcde_dev->dev.platform_data;
- dev_dbg(&mcde_dev->dev, "%s disable dsipll\n",
- __func__);
- pdata->platform_disable_dsipll();
+ if (dsi_use_clk_framework) {
+ clk_disable(chnl->clk_dsi_lp);
+ clk_disable(chnl->clk_dsi_hs);
+ } else {
+ if (dsi_pll_is_enabled && (--dsi_pll_is_enabled == 0)) {
+ struct mcde_platform_data *pdata =
+ mcde_dev->dev.platform_data;
+ dev_dbg(&mcde_dev->dev, "%s disable dsipll\n",
+ __func__);
+ pdata->platform_disable_dsipll();
+ }
+ clk_disable(clock_dsi);
+ clk_disable(clock_dsi_lp);
}
- clk_disable(clock_dsi);
- clk_disable(clock_dsi_lp);
dsi_wfld(chnl->port.link, DSI_MCTL_MAIN_DATA_CTL, LINK_EN, false);
}
@@ -618,7 +641,7 @@ static void disable_mcde_hw(bool force_disable, bool suspend)
if (chnl->port.type == MCDE_PORTTYPE_DSI)
dsi_link_disable(chnl, suspend);
else if (chnl->port.type == MCDE_PORTTYPE_DPI)
- clk_disable(clock_dpi);
+ clk_disable(chnl->clk_dpi);
chnl->formatter_updated = false;
}
if (chnl->esram_is_enabled) {
@@ -1279,8 +1302,15 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
}
}
- if (port->type == MCDE_PORTTYPE_DPI)
- WARN_ON_ONCE(clk_enable(clock_dpi));
+ if (port->type == MCDE_PORTTYPE_DPI) {
+ if (port->phy.dpi.lcd_freq != clk_round_rate(chnl->clk_dpi,
+ port->phy.dpi.lcd_freq))
+ dev_warn(&mcde_dev->dev, "Could not set lcd freq"
+ " to %d\n", port->phy.dpi.lcd_freq);
+ WARN_ON_ONCE(clk_set_rate(chnl->clk_dpi,
+ port->phy.dpi.lcd_freq));
+ WARN_ON_ONCE(clk_enable(chnl->clk_dpi));
+ }
mcde_wfld(MCDE_CR, MCDEEN, true);
chnl->formatter_updated = true;
@@ -2588,10 +2618,32 @@ static struct mcde_chnl_state *_mcde_chnl_get(enum mcde_chnl chnl_id,
chnl->reserved = true;
if (chnl->port.type == MCDE_PORTTYPE_DPI) {
+ chnl->clk_dpi = clk_get(&mcde_dev->dev, CLK_DPI);
if (chnl->port.phy.dpi.tv_mode)
chnl->vcmp_per_field = true;
+ } else if (chnl->port.type == MCDE_PORTTYPE_DSI &&
+ dsi_use_clk_framework) {
+ char dsihs_name[10];
+ char dsilp_name[10];
+
+ sprintf(dsihs_name, "dsihs%d", port->link);
+ sprintf(dsilp_name, "dsilp%d", port->link);
+
+ chnl->clk_dsi_lp = clk_get(&mcde_dev->dev, dsilp_name);
+ chnl->clk_dsi_hs = clk_get(&mcde_dev->dev, dsihs_name);
+ if (port->phy.dsi.lp_freq != clk_round_rate(chnl->clk_dsi_lp,
+ port->phy.dsi.lp_freq))
+ dev_warn(&mcde_dev->dev, "Could not set dsi lp freq"
+ " to %d\n", port->phy.dsi.lp_freq);
+ WARN_ON_ONCE(clk_set_rate(chnl->clk_dsi_lp,
+ port->phy.dsi.lp_freq));
+ if (port->phy.dsi.hs_freq != clk_round_rate(chnl->clk_dsi_hs,
+ port->phy.dsi.hs_freq))
+ dev_warn(&mcde_dev->dev, "Could not set dsi hs freq"
+ " to %d\n", port->phy.dsi.hs_freq);
+ WARN_ON_ONCE(clk_set_rate(chnl->clk_dsi_hs,
+ port->phy.dsi.hs_freq));
}
-
return chnl;
}
@@ -2989,10 +3041,16 @@ void mcde_chnl_put(struct mcde_chnl_state *chnl)
chnl->reserved = false;
if (chnl->port.type == MCDE_PORTTYPE_DPI) {
+ clk_put(chnl->clk_dpi);
if (chnl->port.phy.dpi.tv_mode) {
chnl->vcmp_per_field = false;
chnl->even_vcmp = false;
}
+ } else if (chnl->port.type == MCDE_PORTTYPE_DSI) {
+ if (dsi_use_clk_framework) {
+ clk_put(chnl->clk_dsi_lp);
+ clk_put(chnl->clk_dsi_hs);
+ }
}
dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
@@ -3283,39 +3341,32 @@ static int init_clocks_and_power(struct platform_device *pdev)
__func__);
}
- /*
- * DSI, DSI LP and DPI clocks are not necessary to get
- * There can be platforms that not have DSI, DPI support
- */
- clock_dsi = clk_get(&pdev->dev, pdata->clock_dsi_id);
- if (IS_ERR(clock_dsi))
- dev_dbg(&pdev->dev, "%s: Failed to get clock '%s'\n",
- __func__, pdata->clock_dsi_id);
+ if (!dsi_use_clk_framework) {
+ clock_dsi = clk_get(&pdev->dev, pdata->clock_dsi_id);
+ if (IS_ERR(clock_dsi))
+ dev_dbg(&pdev->dev, "%s: Failed to get clock '%s'\n",
+ __func__, pdata->clock_dsi_id);
- clock_dsi_lp = clk_get(&pdev->dev, pdata->clock_dsi_lp_id);
- if (IS_ERR(clock_dsi_lp))
- dev_dbg(&pdev->dev, "%s: Failed to get clock '%s'\n",
+ clock_dsi_lp = clk_get(&pdev->dev, pdata->clock_dsi_lp_id);
+ if (IS_ERR(clock_dsi_lp))
+ dev_dbg(&pdev->dev, "%s: Failed to get clock '%s'\n",
__func__, pdata->clock_dsi_lp_id);
+ }
- clock_dpi = clk_get(&pdev->dev, pdata->clock_dpi_id);
- if (IS_ERR(clock_dpi))
- dev_dbg(&pdev->dev, "%s: Failed to get clock '%s'\n",
- __func__, pdata->clock_dpi_id);
-
- clock_mcde = clk_get(&pdev->dev, pdata->clock_mcde_id);
+ clock_mcde = clk_get(&pdev->dev, CLK_MCDE);
if (IS_ERR(clock_mcde)) {
ret = PTR_ERR(clock_mcde);
- dev_warn(&pdev->dev, "%s: Failed to get clock '%s'\n",
- __func__, pdata->clock_mcde_id);
+ dev_warn(&pdev->dev, "%s: Failed to get mcde_clk\n", __func__);
goto clk_mcde_err;
}
return ret;
clk_mcde_err:
- clk_put(clock_dpi);
- clk_put(clock_dsi_lp);
- clk_put(clock_dsi);
+ if (!dsi_use_clk_framework) {
+ clk_put(clock_dsi_lp);
+ clk_put(clock_dsi);
+ }
if (regulator_vana)
regulator_put(regulator_vana);
@@ -3331,9 +3382,10 @@ static void remove_clocks_and_power(struct platform_device *pdev)
{
/* REVIEW: Release only if exist */
/* REVIEW: Remove make sure MCDE is done */
- clk_put(clock_dpi);
- clk_put(clock_dsi_lp);
- clk_put(clock_dsi);
+ if (!dsi_use_clk_framework) {
+ clk_put(clock_dsi_lp);
+ clk_put(clock_dsi);
+ }
clk_put(clock_mcde);
if (regulator_vana)
regulator_put(regulator_vana);
@@ -3369,6 +3421,7 @@ static int probe_hw(struct platform_device *pdev)
input_fifo_size = 128;
output_fifo_ab_size = 640;
output_fifo_c0c1_size = 160;
+ dsi_use_clk_framework = true;
dev_info(&mcde_dev->dev, "db8500 V2 HW\n");
break;
case MCDE_VERSION_4_0_4:
@@ -3378,6 +3431,7 @@ static int probe_hw(struct platform_device *pdev)
input_fifo_size = 80;
output_fifo_ab_size = 320;
dsi_ifc_is_supported = false;
+ dsi_use_clk_framework = false;
dev_info(&mcde_dev->dev, "db5500 V2 HW\n");
break;
case MCDE_VERSION_4_1_3:
@@ -3388,6 +3442,7 @@ static int probe_hw(struct platform_device *pdev)
input_fifo_size = 192;
output_fifo_ab_size = 640;
output_fifo_c0c1_size = 160;
+ dsi_use_clk_framework = false;
dev_info(&mcde_dev->dev, "db9540 V1 HW\n");
break;
case MCDE_VERSION_3_0_5:
diff --git a/include/video/mcde.h b/include/video/mcde.h
index 39b190c6403..015350f4495 100644
--- a/include/video/mcde.h
+++ b/include/video/mcde.h
@@ -138,6 +138,9 @@ struct mcde_port {
*/
u32 vid_wakeup_time;
+ u32 hs_freq;
+ u32 lp_freq;
+
/* DSI data lanes are swapped if true */
bool data_lanes_swap;
} dsi;
@@ -146,6 +149,7 @@ struct mcde_port {
bool tv_mode;
u16 clock_div; /* use 0 or 1 for no clock divider */
u32 polarity; /* see DPI_ACT_LOW_* definitions */
+ u32 lcd_freq;
} dpi;
} phy;
};