summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
};