|
@@ -34,6 +34,8 @@
|
|
|
#include <linux/pm_runtime.h>
|
|
|
#include <linux/gfp.h>
|
|
|
#include <linux/sizes.h>
|
|
|
+#include <linux/mfd/syscon.h>
|
|
|
+#include <linux/regmap.h>
|
|
|
#include <linux/of.h>
|
|
|
|
|
|
#include <video/omapdss.h>
|
|
@@ -78,6 +80,8 @@ struct dss_features {
|
|
|
static struct {
|
|
|
struct platform_device *pdev;
|
|
|
void __iomem *base;
|
|
|
+ struct regmap *syscon_pll_ctrl;
|
|
|
+ u32 syscon_pll_ctrl_offset;
|
|
|
|
|
|
struct clk *parent_clk;
|
|
|
struct clk *dss_clk;
|
|
@@ -158,6 +162,99 @@ static void dss_restore_context(void)
|
|
|
#undef SR
|
|
|
#undef RR
|
|
|
|
|
|
+void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable)
|
|
|
+{
|
|
|
+ unsigned shift;
|
|
|
+ unsigned val;
|
|
|
+
|
|
|
+ if (!dss.syscon_pll_ctrl)
|
|
|
+ return;
|
|
|
+
|
|
|
+ val = !enable;
|
|
|
+
|
|
|
+ switch (pll_id) {
|
|
|
+ case DSS_PLL_VIDEO1:
|
|
|
+ shift = 0;
|
|
|
+ break;
|
|
|
+ case DSS_PLL_VIDEO2:
|
|
|
+ shift = 1;
|
|
|
+ break;
|
|
|
+ case DSS_PLL_HDMI:
|
|
|
+ shift = 2;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ DSSERR("illegal DSS PLL ID %d\n", pll_id);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
|
|
|
+ 1 << shift, val << shift);
|
|
|
+}
|
|
|
+
|
|
|
+void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
|
|
|
+ enum omap_channel channel)
|
|
|
+{
|
|
|
+ unsigned shift, val;
|
|
|
+
|
|
|
+ if (!dss.syscon_pll_ctrl)
|
|
|
+ return;
|
|
|
+
|
|
|
+ switch (channel) {
|
|
|
+ case OMAP_DSS_CHANNEL_LCD:
|
|
|
+ shift = 3;
|
|
|
+
|
|
|
+ switch (pll_id) {
|
|
|
+ case DSS_PLL_VIDEO1:
|
|
|
+ val = 0; break;
|
|
|
+ case DSS_PLL_HDMI:
|
|
|
+ val = 1; break;
|
|
|
+ default:
|
|
|
+ DSSERR("error in PLL mux config for LCD\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ case OMAP_DSS_CHANNEL_LCD2:
|
|
|
+ shift = 5;
|
|
|
+
|
|
|
+ switch (pll_id) {
|
|
|
+ case DSS_PLL_VIDEO1:
|
|
|
+ val = 0; break;
|
|
|
+ case DSS_PLL_VIDEO2:
|
|
|
+ val = 1; break;
|
|
|
+ case DSS_PLL_HDMI:
|
|
|
+ val = 2; break;
|
|
|
+ default:
|
|
|
+ DSSERR("error in PLL mux config for LCD2\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ case OMAP_DSS_CHANNEL_LCD3:
|
|
|
+ shift = 7;
|
|
|
+
|
|
|
+ switch (pll_id) {
|
|
|
+ case DSS_PLL_VIDEO1:
|
|
|
+ val = 1; break;
|
|
|
+ case DSS_PLL_VIDEO2:
|
|
|
+ val = 0; break;
|
|
|
+ case DSS_PLL_HDMI:
|
|
|
+ val = 2; break;
|
|
|
+ default:
|
|
|
+ DSSERR("error in PLL mux config for LCD3\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ DSSERR("error in PLL mux config\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
|
|
|
+ 0x3 << shift, val << shift);
|
|
|
+}
|
|
|
+
|
|
|
void dss_sdi_init(int datapairs)
|
|
|
{
|
|
|
u32 l;
|
|
@@ -923,6 +1020,7 @@ static void __exit dss_uninit_ports(struct platform_device *pdev)
|
|
|
static int __init omap_dsshw_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
struct resource *dss_mem;
|
|
|
+ struct device_node *np = pdev->dev.of_node;
|
|
|
u32 rev;
|
|
|
int r;
|
|
|
|
|
@@ -979,6 +1077,23 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
|
|
|
|
|
|
dss_init_ports(pdev);
|
|
|
|
|
|
+ if (np && of_property_read_bool(np, "syscon-pll-ctrl")) {
|
|
|
+ dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np,
|
|
|
+ "syscon-pll-ctrl");
|
|
|
+ if (IS_ERR(dss.syscon_pll_ctrl)) {
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "failed to get syscon-pll-ctrl regmap\n");
|
|
|
+ return PTR_ERR(dss.syscon_pll_ctrl);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1,
|
|
|
+ &dss.syscon_pll_ctrl_offset)) {
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "failed to get syscon-pll-ctrl offset\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
rev = dss_read_reg(DSS_REVISION);
|
|
|
printk(KERN_INFO "OMAP DSS rev %d.%d\n",
|
|
|
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
|