Merge branches '3.19/omapdss' and '3.19/simplefb' into fbdev
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 8 Dec 2014 07:16:31 +0000 (09:16 +0200)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 8 Dec 2014 07:16:31 +0000 (09:16 +0200)
Merge fbdev topic branches.

52 files changed:
drivers/video/fbdev/Kconfig
drivers/video/fbdev/amba-clcd.c
drivers/video/fbdev/arkfb.c
drivers/video/fbdev/mmp/core.c
drivers/video/fbdev/mmp/hw/mmp_ctrl.c
drivers/video/fbdev/mx3fb.c
drivers/video/fbdev/mxsfb.c
drivers/video/fbdev/omap2/displays-new/connector-dvi.c
drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
drivers/video/fbdev/omap2/dss/Kconfig
drivers/video/fbdev/omap2/dss/Makefile
drivers/video/fbdev/omap2/dss/dispc.c
drivers/video/fbdev/omap2/dss/dpi.c
drivers/video/fbdev/omap2/dss/dsi.c
drivers/video/fbdev/omap2/dss/dss-of.c
drivers/video/fbdev/omap2/dss/dss.c
drivers/video/fbdev/omap2/dss/dss.h
drivers/video/fbdev/omap2/dss/dss_features.c
drivers/video/fbdev/omap2/dss/dss_features.h
drivers/video/fbdev/omap2/dss/hdmi.h
drivers/video/fbdev/omap2/dss/hdmi4.c
drivers/video/fbdev/omap2/dss/hdmi4_core.c
drivers/video/fbdev/omap2/dss/hdmi4_core.h
drivers/video/fbdev/omap2/dss/hdmi5.c
drivers/video/fbdev/omap2/dss/hdmi5_core.c
drivers/video/fbdev/omap2/dss/hdmi5_core.h
drivers/video/fbdev/omap2/dss/hdmi_common.c
drivers/video/fbdev/omap2/dss/hdmi_phy.c
drivers/video/fbdev/omap2/dss/hdmi_pll.c
drivers/video/fbdev/omap2/dss/hdmi_wp.c
drivers/video/fbdev/omap2/dss/output.c
drivers/video/fbdev/omap2/dss/pll.c [new file with mode: 0644]
drivers/video/fbdev/omap2/dss/sdi.c
drivers/video/fbdev/s3fb.c
drivers/video/fbdev/sh_mobile_lcdcfb.c
drivers/video/fbdev/sis/sis_main.c
drivers/video/fbdev/sm501fb.c
drivers/video/fbdev/smscufx.c
drivers/video/fbdev/udlfb.c
drivers/video/fbdev/uvesafb.c
drivers/video/fbdev/via/viafbdev.c
drivers/video/fbdev/vt8623fb.c
include/sound/omap-hdmi-audio.h [new file with mode: 0644]
include/video/omapdss.h
sound/soc/omap/Kconfig
sound/soc/omap/Makefile
sound/soc/omap/omap-hdmi-audio.c [new file with mode: 0644]
sound/soc/omap/omap-hdmi-card.c [deleted file]
sound/soc/omap/omap-hdmi.c [deleted file]
sound/soc/omap/omap-hdmi.h [deleted file]

index c7bf606a87064491525563ae16a3a36c8092431b..025b439d4fe14127f52661e4df8fea779a03db78 100644 (file)
@@ -2425,7 +2425,7 @@ config FB_JZ4740
 
 config FB_MXS
        tristate "MXS LCD framebuffer support"
-       depends on FB && ARCH_MXS
+       depends on FB && (ARCH_MXS || ARCH_MXC)
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index 6ad23bd3523a991b8fc9096adc272708e83c85dc..32c0b6b28097f115f5a701d7a7d59f50d92d147d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/hardirq.h>
-#include <linux/dma-mapping.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_graph.h>
index adc4ea2cc5a0098c1c717ff69cc25915402989c6..b305a1e7cc765d94dfdbb853d233ab2015620755 100644 (file)
@@ -1016,7 +1016,7 @@ static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
 
-       par->state.vgabase = (void __iomem *) vga_res.start;
+       par->state.vgabase = (void __iomem *) (unsigned long) vga_res.start;
 
        /* FIXME get memsize */
        regval = vga_rseq(par->state.vgabase, 0x10);
index b563b920f15941b356d39b6703856aadd92f6dbd..a0f496049db7dcae8b2b2fbf833de980297e2ab4 100644 (file)
@@ -223,10 +223,10 @@ struct mmp_path *mmp_register_path(struct mmp_path_info *info)
 EXPORT_SYMBOL_GPL(mmp_register_path);
 
 /*
- * mmp_unregister_path - unregister and destory path
- * @p: path to be destoried.
+ * mmp_unregister_path - unregister and destroy path
+ * @p: path to be destroyed.
  *
- * this function registers path and destorys it.
+ * this function registers path and destroys it.
  */
 void mmp_unregister_path(struct mmp_path *path)
 {
index 8621a9f2bdcc63b96da033e29e69da099a74c19c..3c12bd83b561734e3b91f3135d6155dbdc6d92d8 100644 (file)
@@ -441,8 +441,7 @@ static void path_deinit(struct mmphw_path_plat *path_plat)
        if (!path_plat)
                return;
 
-       if (path_plat->path)
-               mmp_unregister_path(path_plat->path);
+       mmp_unregister_path(path_plat->path);
 }
 
 static int mmphw_probe(struct platform_device *pdev)
index 23ec781e9a619a6f4eb745b76cc9a7343eca6eca..f23fca0be9d728d020b1e9c6b8a8acb6fb41c399 100644 (file)
@@ -334,8 +334,7 @@ static void mx3fb_init_backlight(struct mx3fb_data *fbd)
 
 static void mx3fb_exit_backlight(struct mx3fb_data *fbd)
 {
-       if (fbd->bl)
-               backlight_device_unregister(fbd->bl);
+       backlight_device_unregister(fbd->bl);
 }
 
 static void mx3fb_dma_done(void *);
index accf48a2cce43e16d8ebeea80807df2b32c9cc76..f8ac4a452f26d5346613dc981e4eb25ed3992cef 100644 (file)
@@ -172,6 +172,8 @@ struct mxsfb_info {
        struct fb_info fb_info;
        struct platform_device *pdev;
        struct clk *clk;
+       struct clk *clk_axi;
+       struct clk *clk_disp_axi;
        void __iomem *base;     /* registers */
        unsigned allocated_size;
        int enabled;
@@ -331,6 +333,11 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
                }
        }
 
+       if (host->clk_axi)
+               clk_prepare_enable(host->clk_axi);
+
+       if (host->clk_disp_axi)
+               clk_prepare_enable(host->clk_disp_axi);
        clk_prepare_enable(host->clk);
        clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
 
@@ -374,6 +381,10 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
        writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
 
        clk_disable_unprepare(host->clk);
+       if (host->clk_disp_axi)
+               clk_disable_unprepare(host->clk_disp_axi);
+       if (host->clk_axi)
+               clk_disable_unprepare(host->clk_axi);
 
        host->enabled = 0;
 
@@ -867,6 +878,14 @@ static int mxsfb_probe(struct platform_device *pdev)
                goto fb_release;
        }
 
+       host->clk_axi = devm_clk_get(&host->pdev->dev, "axi");
+       if (IS_ERR(host->clk_axi))
+               host->clk_axi = NULL;
+
+       host->clk_disp_axi = devm_clk_get(&host->pdev->dev, "disp_axi");
+       if (IS_ERR(host->clk_disp_axi))
+               host->clk_disp_axi = NULL;
+
        host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd");
        if (IS_ERR(host->reg_lcd))
                host->reg_lcd = NULL;
index 2dfb6e5ff0cc135b32055a2fb5e9a8d6abad29c4..3d38e478bc647402f56f395567847bce88da649f 100644 (file)
@@ -262,8 +262,7 @@ static int dvic_probe_pdata(struct platform_device *pdev)
 
        in = omap_dss_find_output(pdata->source);
        if (in == NULL) {
-               if (ddata->i2c_adapter)
-                       i2c_put_adapter(ddata->i2c_adapter);
+               i2c_put_adapter(ddata->i2c_adapter);
 
                dev_err(&pdev->dev, "Failed to find video source\n");
                return -EPROBE_DEFER;
@@ -352,8 +351,7 @@ static int dvic_probe(struct platform_device *pdev)
 err_reg:
        omap_dss_put_device(ddata->in);
 
-       if (ddata->i2c_adapter)
-               i2c_put_adapter(ddata->i2c_adapter);
+       i2c_put_adapter(ddata->i2c_adapter);
 
        return r;
 }
@@ -371,8 +369,7 @@ static int __exit dvic_remove(struct platform_device *pdev)
 
        omap_dss_put_device(in);
 
-       if (ddata->i2c_adapter)
-               i2c_put_adapter(ddata->i2c_adapter);
+       i2c_put_adapter(ddata->i2c_adapter);
 
        return 0;
 }
index 7b25967a91ebc6235c170e7925ddb229ed8b34df..219f14f596721af92f56bf83001da799bc6e364c 100644 (file)
@@ -170,98 +170,6 @@ static bool hdmic_detect(struct omap_dss_device *dssdev)
                return in->ops.hdmi->detect(in);
 }
 
-static int hdmic_audio_enable(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-       int r;
-
-       /* enable audio only if the display is active */
-       if (!omapdss_device_is_enabled(dssdev))
-               return -EPERM;
-
-       r = in->ops.hdmi->audio_enable(in);
-       if (r)
-               return r;
-
-       dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
-
-       return 0;
-}
-
-static void hdmic_audio_disable(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       in->ops.hdmi->audio_disable(in);
-
-       dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
-}
-
-static int hdmic_audio_start(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-       int r;
-
-       /*
-        * No need to check the panel state. It was checked when trasitioning
-        * to AUDIO_ENABLED.
-        */
-       if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED)
-               return -EPERM;
-
-       r = in->ops.hdmi->audio_start(in);
-       if (r)
-               return r;
-
-       dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
-
-       return 0;
-}
-
-static void hdmic_audio_stop(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       in->ops.hdmi->audio_stop(in);
-
-       dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
-}
-
-static bool hdmic_audio_supported(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       if (!omapdss_device_is_enabled(dssdev))
-               return false;
-
-       return in->ops.hdmi->audio_supported(in);
-}
-
-static int hdmic_audio_config(struct omap_dss_device *dssdev,
-               struct omap_dss_audio *audio)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-       int r;
-
-       /* config audio only if the display is active */
-       if (!omapdss_device_is_enabled(dssdev))
-               return -EPERM;
-
-       r = in->ops.hdmi->audio_config(in, audio);
-       if (r)
-               return r;
-
-       dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
-
-       return 0;
-}
-
 static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
@@ -296,13 +204,6 @@ static struct omap_dss_driver hdmic_driver = {
        .detect                 = hdmic_detect,
        .set_hdmi_mode          = hdmic_set_hdmi_mode,
        .set_hdmi_infoframe     = hdmic_set_infoframe,
-
-       .audio_enable           = hdmic_audio_enable,
-       .audio_disable          = hdmic_audio_disable,
-       .audio_start            = hdmic_audio_start,
-       .audio_stop             = hdmic_audio_stop,
-       .audio_supported        = hdmic_audio_supported,
-       .audio_config           = hdmic_audio_config,
 };
 
 static int hdmic_probe_pdata(struct platform_device *pdev)
index 47ee7cdee1c5881a727f97d1863de1f26d6efcc8..e349064ed61521382d3b80e397de322cea5400b2 100644 (file)
@@ -249,6 +249,7 @@ static int tfp410_probe(struct platform_device *pdev)
        dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
        dssdev->owner = THIS_MODULE;
        dssdev->phy.dpi.data_lines = ddata->data_lines;
+       dssdev->port_num = 1;
 
        r = omapdss_register_output(dssdev);
        if (r) {
index c4abd56dd84697e306e649ff0365fb4504714812..c7a3ce2c5120632133985f997cbd8da18e3540d2 100644 (file)
@@ -193,55 +193,6 @@ static bool tpd_detect(struct omap_dss_device *dssdev)
        return gpio_get_value_cansleep(ddata->hpd_gpio);
 }
 
-static int tpd_audio_enable(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       return in->ops.hdmi->audio_enable(in);
-}
-
-static void tpd_audio_disable(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       in->ops.hdmi->audio_disable(in);
-}
-
-static int tpd_audio_start(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       return in->ops.hdmi->audio_start(in);
-}
-
-static void tpd_audio_stop(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       in->ops.hdmi->audio_stop(in);
-}
-
-static bool tpd_audio_supported(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       return in->ops.hdmi->audio_supported(in);
-}
-
-static int tpd_audio_config(struct omap_dss_device *dssdev,
-               struct omap_dss_audio *audio)
-{
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
-
-       return in->ops.hdmi->audio_config(in, audio);
-}
-
 static int tpd_set_infoframe(struct omap_dss_device *dssdev,
                const struct hdmi_avi_infoframe *avi)
 {
@@ -275,13 +226,6 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
        .detect                 = tpd_detect,
        .set_infoframe          = tpd_set_infoframe,
        .set_hdmi_mode          = tpd_set_hdmi_mode,
-
-       .audio_enable           = tpd_audio_enable,
-       .audio_disable          = tpd_audio_disable,
-       .audio_start            = tpd_audio_start,
-       .audio_stop             = tpd_audio_stop,
-       .audio_supported        = tpd_audio_supported,
-       .audio_config           = tpd_audio_config,
 };
 
 static int tpd_probe_pdata(struct platform_device *pdev)
@@ -409,6 +353,7 @@ static int tpd_probe(struct platform_device *pdev)
        dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
        dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
        dssdev->owner = THIS_MODULE;
+       dssdev->port_num = 1;
 
        in = ddata->in;
 
index 3d5eb6c36c22c2306073c563b47d8277f0bb0ed7..d1fa730c7d549c9cb27fac5ae52a30cb502c3898 100644 (file)
@@ -74,9 +74,6 @@ config OMAP4_DSS_HDMI
        help
          HDMI support for OMAP4 based SoCs.
 
-config OMAP4_DSS_HDMI_AUDIO
-       bool
-
 config OMAP5_DSS_HDMI
        bool "HDMI support for OMAP5"
        default n
@@ -86,10 +83,6 @@ config OMAP5_DSS_HDMI
          Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI
          specification.
 
-config OMAP5_DSS_HDMI_AUDIO
-       depends on OMAP5_DSS_HDMI
-       bool
-
 config OMAP2_DSS_SDI
        bool "SDI support"
         default n
index 245f933060eed2e91bc27a9d2c3c945f489bc5d2..2ea9d382354c2f143e3901d6646977c38f2983c7 100644 (file)
@@ -2,7 +2,7 @@ obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
 # Core DSS files
 omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
-       output.o dss-of.o
+       output.o dss-of.o pll.o
 # DSS compat layer files
 omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
        dispc-compat.o display-sysfs.o
index 0e9a74bb9fc2d8c1cbd2de9ca73b20f94e5f2199..0729c08ac75aa9a469a4f47906763d38d57e44e7 100644 (file)
@@ -3028,7 +3028,7 @@ static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
 
 unsigned long dispc_fclk_rate(void)
 {
-       struct platform_device *dsidev;
+       struct dss_pll *pll;
        unsigned long r = 0;
 
        switch (dss_get_dispc_clk_source()) {
@@ -3036,12 +3036,12 @@ unsigned long dispc_fclk_rate(void)
                r = dss_get_dispc_clk_rate();
                break;
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-               dsidev = dsi_get_dsidev_from_id(0);
-               r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+               pll = dss_pll_find("dsi0");
+               r = pll->cinfo.clkout[0];
                break;
        case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-               dsidev = dsi_get_dsidev_from_id(1);
-               r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+               pll = dss_pll_find("dsi1");
+               r = pll->cinfo.clkout[0];
                break;
        default:
                BUG();
@@ -3053,7 +3053,7 @@ unsigned long dispc_fclk_rate(void)
 
 unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
 {
-       struct platform_device *dsidev;
+       struct dss_pll *pll;
        int lcd;
        unsigned long r;
        u32 l;
@@ -3068,12 +3068,12 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
                        r = dss_get_dispc_clk_rate();
                        break;
                case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-                       dsidev = dsi_get_dsidev_from_id(0);
-                       r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+                       pll = dss_pll_find("dsi0");
+                       r = pll->cinfo.clkout[0];
                        break;
                case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-                       dsidev = dsi_get_dsidev_from_id(1);
-                       r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+                       pll = dss_pll_find("dsi1");
+                       r = pll->cinfo.clkout[0];
                        break;
                default:
                        BUG();
index 4a3363dae74aa7479722732102ab4e22ca28fbce..2edf5caa002ff1c5007ffda4df1fe437cfd9507a 100644 (file)
 #include <linux/regulator/consumer.h>
 #include <linux/string.h>
 #include <linux/of.h>
+#include <linux/clk.h>
 
 #include <video/omapdss.h>
 
 #include "dss.h"
 #include "dss_features.h"
 
-static struct {
+#define HSDIV_DISPC    0
+
+struct dpi_data {
        struct platform_device *pdev;
 
        struct regulator *vdds_dsi_reg;
-       struct platform_device *dsidev;
+       struct dss_pll *pll;
 
        struct mutex lock;
 
@@ -52,9 +55,20 @@ static struct {
        struct omap_dss_device output;
 
        bool port_initialized;
-} dpi;
+};
+
+static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev)
+{
+       return container_of(dssdev, struct dpi_data, output);
+}
+
+/* only used in non-DT mode */
+static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev)
+{
+       return dev_get_drvdata(&pdev->dev);
+}
 
-static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
+static struct dss_pll *dpi_get_pll(enum omap_channel channel)
 {
        /*
         * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
@@ -75,9 +89,9 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
        case OMAPDSS_VER_OMAP4:
                switch (channel) {
                case OMAP_DSS_CHANNEL_LCD:
-                       return dsi_get_dsidev_from_id(0);
+                       return dss_pll_find("dsi0");
                case OMAP_DSS_CHANNEL_LCD2:
-                       return dsi_get_dsidev_from_id(1);
+                       return dss_pll_find("dsi1");
                default:
                        return NULL;
                }
@@ -85,9 +99,9 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
        case OMAPDSS_VER_OMAP5:
                switch (channel) {
                case OMAP_DSS_CHANNEL_LCD:
-                       return dsi_get_dsidev_from_id(0);
+                       return dss_pll_find("dsi0");
                case OMAP_DSS_CHANNEL_LCD3:
-                       return dsi_get_dsidev_from_id(1);
+                       return dss_pll_find("dsi1");
                default:
                        return NULL;
                }
@@ -114,7 +128,7 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
 }
 
 struct dpi_clk_calc_ctx {
-       struct platform_device *dsidev;
+       struct dss_pll *pll;
 
        /* inputs */
 
@@ -122,7 +136,7 @@ struct dpi_clk_calc_ctx {
 
        /* outputs */
 
-       struct dsi_clock_info dsi_cinfo;
+       struct dss_pll_clock_info dsi_cinfo;
        unsigned long fck;
        struct dispc_clock_info dispc_cinfo;
 };
@@ -154,7 +168,7 @@ static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
 }
 
 
-static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+static bool dpi_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
                void *data)
 {
        struct dpi_clk_calc_ctx *ctx = data;
@@ -164,30 +178,31 @@ static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
         * shifted. So skip all odd dividers when the pixel clock is on the
         * higher side.
         */
-       if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 100000000)
+       if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000)
                return false;
 
-       ctx->dsi_cinfo.regm_dispc = regm_dispc;
-       ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+       ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc;
+       ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc;
 
        return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
                        dpi_calc_dispc_cb, ctx);
 }
 
 
-static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
-               unsigned long pll,
+static bool dpi_calc_pll_cb(int n, int m, unsigned long fint,
+               unsigned long clkdco,
                void *data)
 {
        struct dpi_clk_calc_ctx *ctx = data;
 
-       ctx->dsi_cinfo.regn = regn;
-       ctx->dsi_cinfo.regm = regm;
+       ctx->dsi_cinfo.n = n;
+       ctx->dsi_cinfo.m = m;
        ctx->dsi_cinfo.fint = fint;
-       ctx->dsi_cinfo.clkin4ddr = pll;
+       ctx->dsi_cinfo.clkdco = clkdco;
 
-       return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
-                       dpi_calc_hsdiv_cb, ctx);
+       return dss_pll_hsdiv_calc(ctx->pll, clkdco,
+               ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
+               dpi_calc_hsdiv_cb, ctx);
 }
 
 static bool dpi_calc_dss_cb(unsigned long fck, void *data)
@@ -200,23 +215,23 @@ static bool dpi_calc_dss_cb(unsigned long fck, void *data)
                        dpi_calc_dispc_cb, ctx);
 }
 
-static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+static bool dpi_dsi_clk_calc(struct dpi_data *dpi, unsigned long pck,
+               struct dpi_clk_calc_ctx *ctx)
 {
        unsigned long clkin;
        unsigned long pll_min, pll_max;
 
-       clkin = dsi_get_pll_clkin(dpi.dsidev);
-
        memset(ctx, 0, sizeof(*ctx));
-       ctx->dsidev = dpi.dsidev;
+       ctx->pll = dpi->pll;
        ctx->pck_min = pck - 1000;
        ctx->pck_max = pck + 1000;
-       ctx->dsi_cinfo.clkin = clkin;
 
        pll_min = 0;
        pll_max = 0;
 
-       return dsi_pll_calc(dpi.dsidev, clkin,
+       clkin = clk_get_rate(ctx->pll->clkin);
+
+       return dss_pll_calc(ctx->pll, clkin,
                        pll_min, pll_max,
                        dpi_calc_pll_cb, ctx);
 }
@@ -252,7 +267,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
 
 
 
-static int dpi_set_dsi_clk(enum omap_channel channel,
+static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel,
                unsigned long pck_req, unsigned long *fck, int *lck_div,
                int *pck_div)
 {
@@ -260,28 +275,28 @@ static int dpi_set_dsi_clk(enum omap_channel channel,
        int r;
        bool ok;
 
-       ok = dpi_dsi_clk_calc(pck_req, &ctx);
+       ok = dpi_dsi_clk_calc(dpi, pck_req, &ctx);
        if (!ok)
                return -EINVAL;
 
-       r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
+       r = dss_pll_set_config(dpi->pll, &ctx.dsi_cinfo);
        if (r)
                return r;
 
        dss_select_lcd_clk_source(channel,
                        dpi_get_alt_clk_src(channel));
 
-       dpi.mgr_config.clock_info = ctx.dispc_cinfo;
+       dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
-       *fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+       *fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC];
        *lck_div = ctx.dispc_cinfo.lck_div;
        *pck_div = ctx.dispc_cinfo.pck_div;
 
        return 0;
 }
 
-static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
-               int *lck_div, int *pck_div)
+static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
+               unsigned long *fck, int *lck_div, int *pck_div)
 {
        struct dpi_clk_calc_ctx ctx;
        int r;
@@ -295,7 +310,7 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
        if (r)
                return r;
 
-       dpi.mgr_config.clock_info = ctx.dispc_cinfo;
+       dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
        *fck = ctx.fck;
        *lck_div = ctx.dispc_cinfo.lck_div;
@@ -304,19 +319,21 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
        return 0;
 }
 
-static int dpi_set_mode(struct omap_overlay_manager *mgr)
+static int dpi_set_mode(struct dpi_data *dpi)
 {
-       struct omap_video_timings *t = &dpi.timings;
+       struct omap_dss_device *out = &dpi->output;
+       struct omap_overlay_manager *mgr = out->manager;
+       struct omap_video_timings *t = &dpi->timings;
        int lck_div = 0, pck_div = 0;
        unsigned long fck = 0;
        unsigned long pck;
        int r = 0;
 
-       if (dpi.dsidev)
-               r = dpi_set_dsi_clk(mgr->id, t->pixelclock, &fck,
+       if (dpi->pll)
+               r = dpi_set_dsi_clk(dpi, mgr->id, t->pixelclock, &fck,
                                &lck_div, &pck_div);
        else
-               r = dpi_set_dispc_clk(t->pixelclock, &fck,
+               r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
                                &lck_div, &pck_div);
        if (r)
                return r;
@@ -335,28 +352,32 @@ static int dpi_set_mode(struct omap_overlay_manager *mgr)
        return 0;
 }
 
-static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
+static void dpi_config_lcd_manager(struct dpi_data *dpi)
 {
-       dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
+       struct omap_dss_device *out = &dpi->output;
+       struct omap_overlay_manager *mgr = out->manager;
+
+       dpi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
 
-       dpi.mgr_config.stallmode = false;
-       dpi.mgr_config.fifohandcheck = false;
+       dpi->mgr_config.stallmode = false;
+       dpi->mgr_config.fifohandcheck = false;
 
-       dpi.mgr_config.video_port_width = dpi.data_lines;
+       dpi->mgr_config.video_port_width = dpi->data_lines;
 
-       dpi.mgr_config.lcden_sig_polarity = 0;
+       dpi->mgr_config.lcden_sig_polarity = 0;
 
-       dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
+       dss_mgr_set_lcd_config(mgr, &dpi->mgr_config);
 }
 
 static int dpi_display_enable(struct omap_dss_device *dssdev)
 {
-       struct omap_dss_device *out = &dpi.output;
+       struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+       struct omap_dss_device *out = &dpi->output;
        int r;
 
-       mutex_lock(&dpi.lock);
+       mutex_lock(&dpi->lock);
 
-       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi->vdds_dsi_reg) {
                DSSERR("no VDSS_DSI regulator\n");
                r = -ENODEV;
                goto err_no_reg;
@@ -369,7 +390,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
        }
 
        if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
-               r = regulator_enable(dpi.vdds_dsi_reg);
+               r = regulator_enable(dpi->vdds_dsi_reg);
                if (r)
                        goto err_reg_enable;
        }
@@ -378,25 +399,21 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err_get_dispc;
 
-       r = dss_dpi_select_source(out->manager->id);
+       r = dss_dpi_select_source(out->port_num, out->manager->id);
        if (r)
                goto err_src_sel;
 
-       if (dpi.dsidev) {
-               r = dsi_runtime_get(dpi.dsidev);
-               if (r)
-                       goto err_get_dsi;
-
-               r = dsi_pll_init(dpi.dsidev, 0, 1);
+       if (dpi->pll) {
+               r = dss_pll_enable(dpi->pll);
                if (r)
                        goto err_dsi_pll_init;
        }
 
-       r = dpi_set_mode(out->manager);
+       r = dpi_set_mode(dpi);
        if (r)
                goto err_set_mode;
 
-       dpi_config_lcd_manager(out->manager);
+       dpi_config_lcd_manager(dpi);
 
        mdelay(2);
 
@@ -404,78 +421,80 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err_mgr_enable;
 
-       mutex_unlock(&dpi.lock);
+       mutex_unlock(&dpi->lock);
 
        return 0;
 
 err_mgr_enable:
 err_set_mode:
-       if (dpi.dsidev)
-               dsi_pll_uninit(dpi.dsidev, true);
+       if (dpi->pll)
+               dss_pll_disable(dpi->pll);
 err_dsi_pll_init:
-       if (dpi.dsidev)
-               dsi_runtime_put(dpi.dsidev);
-err_get_dsi:
 err_src_sel:
        dispc_runtime_put();
 err_get_dispc:
        if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
-               regulator_disable(dpi.vdds_dsi_reg);
+               regulator_disable(dpi->vdds_dsi_reg);
 err_reg_enable:
 err_no_out_mgr:
 err_no_reg:
-       mutex_unlock(&dpi.lock);
+       mutex_unlock(&dpi->lock);
        return r;
 }
 
 static void dpi_display_disable(struct omap_dss_device *dssdev)
 {
-       struct omap_overlay_manager *mgr = dpi.output.manager;
+       struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+       struct omap_overlay_manager *mgr = dpi->output.manager;
 
-       mutex_lock(&dpi.lock);
+       mutex_lock(&dpi->lock);
 
        dss_mgr_disable(mgr);
 
-       if (dpi.dsidev) {
+       if (dpi->pll) {
                dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
-               dsi_pll_uninit(dpi.dsidev, true);
-               dsi_runtime_put(dpi.dsidev);
+               dss_pll_disable(dpi->pll);
        }
 
        dispc_runtime_put();
 
        if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
-               regulator_disable(dpi.vdds_dsi_reg);
+               regulator_disable(dpi->vdds_dsi_reg);
 
-       mutex_unlock(&dpi.lock);
+       mutex_unlock(&dpi->lock);
 }
 
 static void dpi_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
+       struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+
        DSSDBG("dpi_set_timings\n");
 
-       mutex_lock(&dpi.lock);
+       mutex_lock(&dpi->lock);
 
-       dpi.timings = *timings;
+       dpi->timings = *timings;
 
-       mutex_unlock(&dpi.lock);
+       mutex_unlock(&dpi->lock);
 }
 
 static void dpi_get_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       mutex_lock(&dpi.lock);
+       struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+
+       mutex_lock(&dpi->lock);
 
-       *timings = dpi.timings;
+       *timings = dpi->timings;
 
-       mutex_unlock(&dpi.lock);
+       mutex_unlock(&dpi->lock);
 }
 
 static int dpi_check_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
-       struct omap_overlay_manager *mgr = dpi.output.manager;
+       struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+       struct omap_overlay_manager *mgr = dpi->output.manager;
        int lck_div, pck_div;
        unsigned long fck;
        unsigned long pck;
@@ -488,12 +507,12 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
        if (timings->pixelclock == 0)
                return -EINVAL;
 
-       if (dpi.dsidev) {
-               ok = dpi_dsi_clk_calc(timings->pixelclock, &ctx);
+       if (dpi->pll) {
+               ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx);
                if (!ok)
                        return -EINVAL;
 
-               fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+               fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC];
        } else {
                ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
                if (!ok)
@@ -514,74 +533,69 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
 
 static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
 {
-       mutex_lock(&dpi.lock);
+       struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 
-       dpi.data_lines = data_lines;
+       mutex_lock(&dpi->lock);
 
-       mutex_unlock(&dpi.lock);
+       dpi->data_lines = data_lines;
+
+       mutex_unlock(&dpi->lock);
 }
 
-static int dpi_verify_dsi_pll(struct platform_device *dsidev)
+static int dpi_verify_dsi_pll(struct dss_pll *pll)
 {
        int r;
 
        /* do initial setup with the PLL to see if it is operational */
 
-       r = dsi_runtime_get(dsidev);
+       r = dss_pll_enable(pll);
        if (r)
                return r;
 
-       r = dsi_pll_init(dsidev, 0, 1);
-       if (r) {
-               dsi_runtime_put(dsidev);
-               return r;
-       }
-
-       dsi_pll_uninit(dsidev, true);
-       dsi_runtime_put(dsidev);
+       dss_pll_disable(pll);
 
        return 0;
 }
 
-static int dpi_init_regulator(void)
+static int dpi_init_regulator(struct dpi_data *dpi)
 {
        struct regulator *vdds_dsi;
 
        if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
                return 0;
 
-       if (dpi.vdds_dsi_reg)
+       if (dpi->vdds_dsi_reg)
                return 0;
 
-       vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi");
+       vdds_dsi = devm_regulator_get(&dpi->pdev->dev, "vdds_dsi");
        if (IS_ERR(vdds_dsi)) {
                if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
                        DSSERR("can't get VDDS_DSI regulator\n");
                return PTR_ERR(vdds_dsi);
        }
 
-       dpi.vdds_dsi_reg = vdds_dsi;
+       dpi->vdds_dsi_reg = vdds_dsi;
 
        return 0;
 }
 
-static void dpi_init_pll(void)
+static void dpi_init_pll(struct dpi_data *dpi)
 {
-       struct platform_device *dsidev;
+       struct dss_pll *pll;
 
-       if (dpi.dsidev)
+       if (dpi->pll)
                return;
 
-       dsidev = dpi_get_dsidev(dpi.output.dispc_channel);
-       if (!dsidev)
+       pll = dpi_get_pll(dpi->output.dispc_channel);
+       if (!pll)
                return;
 
-       if (dpi_verify_dsi_pll(dsidev)) {
+       if (dpi_verify_dsi_pll(pll)) {
                DSSWARN("DSI PLL not operational\n");
                return;
        }
 
-       dpi.dsidev = dsidev;
+       dpi->pll = pll;
 }
 
 /*
@@ -590,7 +604,7 @@ static void dpi_init_pll(void)
  * the channel in some more dynamic manner, or get the channel as a user
  * parameter.
  */
-static enum omap_channel dpi_get_channel(void)
+static enum omap_channel dpi_get_channel(int port_num)
 {
        switch (omapdss_get_version()) {
        case OMAPDSS_VER_OMAP24xx:
@@ -618,14 +632,15 @@ static enum omap_channel dpi_get_channel(void)
 static int dpi_connect(struct omap_dss_device *dssdev,
                struct omap_dss_device *dst)
 {
+       struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
        struct omap_overlay_manager *mgr;
        int r;
 
-       r = dpi_init_regulator();
+       r = dpi_init_regulator(dpi);
        if (r)
                return r;
 
-       dpi_init_pll();
+       dpi_init_pll(dpi);
 
        mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
        if (!mgr)
@@ -676,13 +691,14 @@ static const struct omapdss_dpi_ops dpi_ops = {
 
 static void dpi_init_output(struct platform_device *pdev)
 {
-       struct omap_dss_device *out = &dpi.output;
+       struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
+       struct omap_dss_device *out = &dpi->output;
 
        out->dev = &pdev->dev;
        out->id = OMAP_DSS_OUTPUT_DPI;
        out->output_type = OMAP_DISPLAY_TYPE_DPI;
        out->name = "dpi.0";
-       out->dispc_channel = dpi_get_channel();
+       out->dispc_channel = dpi_get_channel(0);
        out->ops.dpi = &dpi_ops;
        out->owner = THIS_MODULE;
 
@@ -691,16 +707,69 @@ static void dpi_init_output(struct platform_device *pdev)
 
 static void __exit dpi_uninit_output(struct platform_device *pdev)
 {
-       struct omap_dss_device *out = &dpi.output;
+       struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
+       struct omap_dss_device *out = &dpi->output;
+
+       omapdss_unregister_output(out);
+}
+
+static void dpi_init_output_port(struct platform_device *pdev,
+       struct device_node *port)
+{
+       struct dpi_data *dpi = port->data;
+       struct omap_dss_device *out = &dpi->output;
+       int r;
+       u32 port_num;
+
+       r = of_property_read_u32(port, "reg", &port_num);
+       if (r)
+               port_num = 0;
+
+       switch (port_num) {
+       case 2:
+               out->name = "dpi.2";
+               break;
+       case 1:
+               out->name = "dpi.1";
+               break;
+       case 0:
+       default:
+               out->name = "dpi.0";
+               break;
+       }
+
+       out->dev = &pdev->dev;
+       out->id = OMAP_DSS_OUTPUT_DPI;
+       out->output_type = OMAP_DISPLAY_TYPE_DPI;
+       out->dispc_channel = dpi_get_channel(port_num);
+       out->port_num = port_num;
+       out->ops.dpi = &dpi_ops;
+       out->owner = THIS_MODULE;
+
+       omapdss_register_output(out);
+}
+
+static void __exit dpi_uninit_output_port(struct device_node *port)
+{
+       struct dpi_data *dpi = port->data;
+       struct omap_dss_device *out = &dpi->output;
 
        omapdss_unregister_output(out);
 }
 
 static int omap_dpi_probe(struct platform_device *pdev)
 {
-       dpi.pdev = pdev;
+       struct dpi_data *dpi;
+
+       dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
+       if (!dpi)
+               return -ENOMEM;
 
-       mutex_init(&dpi.lock);
+       dpi->pdev = pdev;
+
+       dev_set_drvdata(&pdev->dev, dpi);
+
+       mutex_init(&dpi->lock);
 
        dpi_init_output(pdev);
 
@@ -736,10 +805,15 @@ void __exit dpi_uninit_platform_driver(void)
 
 int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
 {
+       struct dpi_data *dpi;
        struct device_node *ep;
        u32 datalines;
        int r;
 
+       dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
+       if (!dpi)
+               return -ENOMEM;
+
        ep = omapdss_of_get_next_endpoint(port, NULL);
        if (!ep)
                return 0;
@@ -750,17 +824,18 @@ int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
                goto err_datalines;
        }
 
-       dpi.data_lines = datalines;
+       dpi->data_lines = datalines;
 
        of_node_put(ep);
 
-       dpi.pdev = pdev;
+       dpi->pdev = pdev;
+       port->data = dpi;
 
-       mutex_init(&dpi.lock);
+       mutex_init(&dpi->lock);
 
-       dpi_init_output(pdev);
+       dpi_init_output_port(pdev, port);
 
-       dpi.port_initialized = true;
+       dpi->port_initialized = true;
 
        return 0;
 
@@ -770,10 +845,12 @@ err_datalines:
        return r;
 }
 
-void __exit dpi_uninit_port(void)
+void __exit dpi_uninit_port(struct device_node *port)
 {
-       if (!dpi.port_initialized)
+       struct dpi_data *dpi = port->data;
+
+       if (!dpi->port_initialized)
                return;
 
-       dpi_uninit_output(dpi.pdev);
+       dpi_uninit_output_port(port);
 }
index 0793bc67a275864ece56a4a8605553c5535704ea..73af351594681073cd6c3dac60aa5835cd0abc96 100644 (file)
@@ -219,6 +219,10 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
 
 static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
 
+/* DSI PLL HSDIV indices */
+#define HSDIV_DISPC    0
+#define HSDIV_DSI      1
+
 #define DSI_MAX_NR_ISRS                2
 #define DSI_MAX_NR_LANES       5
 
@@ -271,6 +275,7 @@ struct dsi_isr_tables {
 
 struct dsi_clk_calc_ctx {
        struct platform_device *dsidev;
+       struct dss_pll *pll;
 
        /* inputs */
 
@@ -280,13 +285,18 @@ struct dsi_clk_calc_ctx {
 
        /* outputs */
 
-       struct dsi_clock_info dsi_cinfo;
+       struct dss_pll_clock_info dsi_cinfo;
        struct dispc_clock_info dispc_cinfo;
 
        struct omap_video_timings dispc_vm;
        struct omap_dss_dsi_videomode_timings dsi_vm;
 };
 
+struct dsi_lp_clock_info {
+       unsigned long lp_clk;
+       u16 lp_clk_div;
+};
+
 struct dsi_data {
        struct platform_device *pdev;
        void __iomem *proto_base;
@@ -300,12 +310,14 @@ struct dsi_data {
        bool is_enabled;
 
        struct clk *dss_clk;
-       struct clk *sys_clk;
 
        struct dispc_clock_info user_dispc_cinfo;
-       struct dsi_clock_info user_dsi_cinfo;
+       struct dss_pll_clock_info user_dsi_cinfo;
+
+       struct dsi_lp_clock_info user_lp_cinfo;
+       struct dsi_lp_clock_info current_lp_cinfo;
 
-       struct dsi_clock_info current_cinfo;
+       struct dss_pll pll;
 
        bool vdds_dsi_enabled;
        struct regulator *vdds_dsi_reg;
@@ -321,8 +333,6 @@ struct dsi_data {
        struct mutex lock;
        struct semaphore bus_lock;
 
-       unsigned pll_locked;
-
        spinlock_t irq_lock;
        struct dsi_isr_tables isr_tables;
        /* space for a copy used by the interrupt handler */
@@ -347,7 +357,7 @@ struct dsi_data {
 
        unsigned long cache_req_pck;
        unsigned long cache_clk_freq;
-       struct dsi_clock_info cache_cinfo;
+       struct dss_pll_clock_info cache_cinfo;
 
        u32             errors;
        spinlock_t      errors_lock;
@@ -362,11 +372,6 @@ struct dsi_data {
        spinlock_t irq_stats_lock;
        struct dsi_irq_stats irq_stats;
 #endif
-       /* DSI PLL Parameter Ranges */
-       unsigned long regm_max, regn_max;
-       unsigned long  regm_dispc_max, regm_dsi_max;
-       unsigned long  fint_min, fint_max;
-       unsigned long lpdiv_max;
 
        unsigned num_lanes_supported;
        unsigned line_buffer_size;
@@ -412,7 +417,7 @@ static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss
        return to_platform_device(dssdev->dev);
 }
 
-struct platform_device *dsi_get_dsidev_from_id(int module)
+static struct platform_device *dsi_get_dsidev_from_id(int module)
 {
        struct omap_dss_device *out;
        enum omap_dss_output_id id;
@@ -1134,7 +1139,7 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
        return e;
 }
 
-int dsi_runtime_get(struct platform_device *dsidev)
+static int dsi_runtime_get(struct platform_device *dsidev)
 {
        int r;
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -1146,7 +1151,7 @@ int dsi_runtime_get(struct platform_device *dsidev)
        return r < 0 ? r : 0;
 }
 
-void dsi_runtime_put(struct platform_device *dsidev)
+static void dsi_runtime_put(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        int r;
@@ -1188,23 +1193,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
        return 0;
 }
 
-/* source clock for DSI PLL. this could also be PCLKFREE */
-static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
-               bool enable)
-{
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-       if (enable)
-               clk_prepare_enable(dsi->sys_clk);
-       else
-               clk_disable_unprepare(dsi->sys_clk);
-
-       if (enable && dsi->pll_locked) {
-               if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
-                       DSSERR("cannot lock PLL when enabling clocks\n");
-       }
-}
-
 static void _dsi_print_reset_status(struct platform_device *dsidev)
 {
        u32 l;
@@ -1256,25 +1244,25 @@ static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
        return 0;
 }
 
-unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
+static unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
-       return dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk;
+       return dsi->pll.cinfo.clkout[HSDIV_DISPC];
 }
 
 static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
-       return dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk;
+       return dsi->pll.cinfo.clkout[HSDIV_DSI];
 }
 
 static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
-       return dsi->current_cinfo.clkin4ddr / 16;
+       return dsi->pll.cinfo.clkdco / 16;
 }
 
 static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
@@ -1293,10 +1281,10 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
        return r;
 }
 
-static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
-               unsigned long lp_clk_min, unsigned long lp_clk_max)
+static int dsi_lp_clock_calc(unsigned long dsi_fclk,
+               unsigned long lp_clk_min, unsigned long lp_clk_max,
+               struct dsi_lp_clock_info *lp_cinfo)
 {
-       unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
        unsigned lp_clk_div;
        unsigned long lp_clk;
 
@@ -1306,8 +1294,8 @@ static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
        if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
                return -EINVAL;
 
-       cinfo->lp_clk_div = lp_clk_div;
-       cinfo->lp_clk = lp_clk;
+       lp_cinfo->lp_clk_div = lp_clk_div;
+       lp_cinfo->lp_clk = lp_clk;
 
        return 0;
 }
@@ -1318,10 +1306,12 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
        unsigned long dsi_fclk;
        unsigned lp_clk_div;
        unsigned long lp_clk;
+       unsigned lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
+
 
-       lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div;
+       lp_clk_div = dsi->user_lp_cinfo.lp_clk_div;
 
-       if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max)
+       if (lp_clk_div == 0 || lp_clk_div > lpdiv_max)
                return -EINVAL;
 
        dsi_fclk = dsi_fclk_rate(dsidev);
@@ -1329,8 +1319,8 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
        lp_clk = dsi_fclk / 2 / lp_clk_div;
 
        DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk);
-       dsi->current_cinfo.lp_clk = lp_clk;
-       dsi->current_cinfo.lp_clk_div = lp_clk_div;
+       dsi->current_lp_cinfo.lp_clk = lp_clk;
+       dsi->current_lp_cinfo.lp_clk_div = lp_clk_div;
 
        /* LP_CLK_DIVISOR */
        REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0);
@@ -1391,286 +1381,33 @@ static int dsi_pll_power(struct platform_device *dsidev,
        return 0;
 }
 
-unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
-{
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       return clk_get_rate(dsi->sys_clk);
-}
-
-bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
-               unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
-{
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       int regm, regm_start, regm_stop;
-       unsigned long out_max;
-       unsigned long out;
-
-       out_min = out_min ? out_min : 1;
-       out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-       regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
-       regm_stop = min(pll / out_min, dsi->regm_dispc_max);
-
-       for (regm = regm_start; regm <= regm_stop; ++regm) {
-               out = pll / regm;
-
-               if (func(regm, out, data))
-                       return true;
-       }
-
-       return false;
-}
-
-bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
-               unsigned long pll_min, unsigned long pll_max,
-               dsi_pll_calc_func func, void *data)
-{
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       int regn, regn_start, regn_stop;
-       int regm, regm_start, regm_stop;
-       unsigned long fint, pll;
-       const unsigned long pll_hw_max = 1800000000;
-       unsigned long fint_hw_min, fint_hw_max;
-
-       fint_hw_min = dsi->fint_min;
-       fint_hw_max = dsi->fint_max;
 
-       regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
-       regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
-
-       pll_max = pll_max ? pll_max : ULONG_MAX;
-
-       for (regn = regn_start; regn <= regn_stop; ++regn) {
-               fint = clkin / regn;
-
-               regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
-                               1ul);
-               regm_stop = min3(pll_max / fint / 2,
-                               pll_hw_max / fint / 2,
-                               dsi->regm_max);
-
-               for (regm = regm_start; regm <= regm_stop; ++regm) {
-                       pll = 2 * regm * fint;
-
-                       if (func(regn, regm, fint, pll, data))
-                               return true;
-               }
-       }
-
-       return false;
-}
-
-/* calculate clock rates using dividers in cinfo */
-static int dsi_calc_clock_rates(struct platform_device *dsidev,
-               struct dsi_clock_info *cinfo)
-{
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-       if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
-               return -EINVAL;
-
-       if (cinfo->regm == 0 || cinfo->regm > dsi->regm_max)
-               return -EINVAL;
-
-       if (cinfo->regm_dispc > dsi->regm_dispc_max)
-               return -EINVAL;
-
-       if (cinfo->regm_dsi > dsi->regm_dsi_max)
-               return -EINVAL;
-
-       cinfo->clkin = clk_get_rate(dsi->sys_clk);
-       cinfo->fint = cinfo->clkin / cinfo->regn;
-
-       if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
-               return -EINVAL;
-
-       cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
-
-       if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
-               return -EINVAL;
-
-       if (cinfo->regm_dispc > 0)
-               cinfo->dsi_pll_hsdiv_dispc_clk =
-                       cinfo->clkin4ddr / cinfo->regm_dispc;
-       else
-               cinfo->dsi_pll_hsdiv_dispc_clk = 0;
-
-       if (cinfo->regm_dsi > 0)
-               cinfo->dsi_pll_hsdiv_dsi_clk =
-                       cinfo->clkin4ddr / cinfo->regm_dsi;
-       else
-               cinfo->dsi_pll_hsdiv_dsi_clk = 0;
-
-       return 0;
-}
-
-static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
+static void dsi_pll_calc_dsi_fck(struct dss_pll_clock_info *cinfo)
 {
        unsigned long max_dsi_fck;
 
        max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
 
-       cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
-       cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
+       cinfo->mX[HSDIV_DSI] = DIV_ROUND_UP(cinfo->clkdco, max_dsi_fck);
+       cinfo->clkout[HSDIV_DSI] = cinfo->clkdco / cinfo->mX[HSDIV_DSI];
 }
 
-int dsi_pll_set_clock_div(struct platform_device *dsidev,
-               struct dsi_clock_info *cinfo)
+static int dsi_pll_enable(struct dss_pll *pll)
 {
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
+       struct platform_device *dsidev = dsi->pdev;
        int r = 0;
-       u32 l;
-       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;
-
-       DSSDBG("DSI PLL clock config starts");
-
-       dsi->current_cinfo.clkin = cinfo->clkin;
-       dsi->current_cinfo.fint = cinfo->fint;
-       dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
-       dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
-                       cinfo->dsi_pll_hsdiv_dispc_clk;
-       dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk =
-                       cinfo->dsi_pll_hsdiv_dsi_clk;
-
-       dsi->current_cinfo.regn = cinfo->regn;
-       dsi->current_cinfo.regm = cinfo->regm;
-       dsi->current_cinfo.regm_dispc = cinfo->regm_dispc;
-       dsi->current_cinfo.regm_dsi = cinfo->regm_dsi;
-
-       DSSDBG("DSI Fint %ld\n", cinfo->fint);
-
-       DSSDBG("clkin rate %ld\n", cinfo->clkin);
-
-       /* DSIPHY == CLKIN4DDR */
-       DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n",
-                       cinfo->regm,
-                       cinfo->regn,
-                       cinfo->clkin,
-                       cinfo->clkin4ddr);
-
-       DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
-                       cinfo->clkin4ddr / 1000 / 1000 / 2);
-
-       DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
-
-       DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
-               dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
-               dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
-               cinfo->dsi_pll_hsdiv_dispc_clk);
-       DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
-               dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
-               dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
-               cinfo->dsi_pll_hsdiv_dsi_clk);
-
-       dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
-       dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &regm_start, &regm_end);
-       dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &regm_dispc_start,
-                       &regm_dispc_end);
-       dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &regm_dsi_start,
-                       &regm_dsi_end);
-
-       /* DSI_PLL_AUTOMODE = manual */
-       REG_FLD_MOD(dsidev, DSI_PLL_CONTROL, 0, 0, 0);
-
-       l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION1);
-       l = FLD_MOD(l, 1, 0, 0);                /* DSI_PLL_STOPMODE */
-       /* DSI_PLL_REGN */
-       l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
-       /* DSI_PLL_REGM */
-       l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
-       /* DSI_CLOCK_DIV */
-       l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
-                       regm_dispc_start, regm_dispc_end);
-       /* DSIPROTO_CLOCK_DIV */
-       l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
-                       regm_dsi_start, regm_dsi_end);
-       dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION1, l);
-
-       BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
-
-       l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
-
-       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 = FLD_MOD(l, f, 4, 1);        /* DSI_PLL_FREQSEL */
-       } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
-               f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
-
-               l = FLD_MOD(l, f, 3, 1);        /* PLL_SELFREQDCO */
-       }
-
-       l = FLD_MOD(l, 1, 13, 13);              /* DSI_PLL_REFEN */
-       l = FLD_MOD(l, 0, 14, 14);              /* DSIPHY_CLKINEN */
-       l = FLD_MOD(l, 1, 20, 20);              /* DSI_HSDIVBYPASS */
-       if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
-               l = FLD_MOD(l, 3, 22, 21);      /* REF_SYSCLK = sysclk */
-       dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
-
-       REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0);       /* DSI_PLL_GO */
-
-       if (wait_for_bit_change(dsidev, DSI_PLL_GO, 0, 0) != 0) {
-               DSSERR("dsi pll go bit not going down.\n");
-               r = -EIO;
-               goto err;
-       }
-
-       if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) {
-               DSSERR("cannot lock PLL\n");
-               r = -EIO;
-               goto err;
-       }
-
-       dsi->pll_locked = 1;
-
-       l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
-       l = FLD_MOD(l, 0, 0, 0);        /* DSI_PLL_IDLE */
-       l = FLD_MOD(l, 0, 5, 5);        /* DSI_PLL_PLLLPMODE */
-       l = FLD_MOD(l, 0, 6, 6);        /* DSI_PLL_LOWCURRSTBY */
-       l = FLD_MOD(l, 0, 7, 7);        /* DSI_PLL_TIGHTPHASELOCK */
-       l = FLD_MOD(l, 0, 8, 8);        /* DSI_PLL_DRIFTGUARDEN */
-       l = FLD_MOD(l, 0, 10, 9);       /* DSI_PLL_LOCKSEL */
-       l = FLD_MOD(l, 1, 13, 13);      /* DSI_PLL_REFEN */
-       l = FLD_MOD(l, 1, 14, 14);      /* DSIPHY_CLKINEN */
-       l = FLD_MOD(l, 0, 15, 15);      /* DSI_BYPASSEN */
-       l = FLD_MOD(l, 1, 16, 16);      /* DSS_CLOCK_EN */
-       l = FLD_MOD(l, 0, 17, 17);      /* DSS_CLOCK_PWDN */
-       l = FLD_MOD(l, 1, 18, 18);      /* DSI_PROTO_CLOCK_EN */
-       l = FLD_MOD(l, 0, 19, 19);      /* DSI_PROTO_CLOCK_PWDN */
-       l = FLD_MOD(l, 0, 20, 20);      /* DSI_HSDIVBYPASS */
-       dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
-
-       DSSDBG("PLL config done\n");
-err:
-       return r;
-}
-
-int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
-               bool enable_hsdiv)
-{
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       int r = 0;
-       enum dsi_pll_power_state pwstate;
 
        DSSDBG("PLL init\n");
 
-       /*
-        * It seems that on many OMAPs we need to enable both to have a
-        * functional HSDivider.
-        */
-       enable_hsclk = enable_hsdiv = true;
-
        r = dsi_regulator_init(dsidev);
        if (r)
                return r;
 
-       dsi_enable_pll_clock(dsidev, 1);
+       r = dsi_runtime_get(dsidev);
+       if (r)
+               return r;
+
        /*
         * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
         */
@@ -1697,16 +1434,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
         * fill the whole display. No idea about this */
        dispc_pck_free_enable(0);
 
-       if (enable_hsclk && enable_hsdiv)
-               pwstate = DSI_PLL_POWER_ON_ALL;
-       else if (enable_hsclk)
-               pwstate = DSI_PLL_POWER_ON_HSCLK;
-       else if (enable_hsdiv)
-               pwstate = DSI_PLL_POWER_ON_DIV;
-       else
-               pwstate = DSI_PLL_POWER_OFF;
-
-       r = dsi_pll_power(dsidev, pwstate);
+       r = dsi_pll_power(dsidev, DSI_PLL_POWER_ON_ALL);
 
        if (r)
                goto err1;
@@ -1721,15 +1449,14 @@ err1:
        }
 err0:
        dsi_disable_scp_clk(dsidev);
-       dsi_enable_pll_clock(dsidev, 0);
+       dsi_runtime_put(dsidev);
        return r;
 }
 
-void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
+static void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
-       dsi->pll_locked = 0;
        dsi_pll_power(dsidev, DSI_PLL_POWER_OFF);
        if (disconnect_lanes) {
                WARN_ON(!dsi->vdds_dsi_enabled);
@@ -1738,18 +1465,27 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
        }
 
        dsi_disable_scp_clk(dsidev);
-       dsi_enable_pll_clock(dsidev, 0);
+       dsi_runtime_put(dsidev);
 
        DSSDBG("PLL uninit done\n");
 }
 
+static void dsi_pll_disable(struct dss_pll *pll)
+{
+       struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
+       struct platform_device *dsidev = dsi->pdev;
+
+       dsi_pll_uninit(dsidev, true);
+}
+
 static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
                struct seq_file *s)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       struct dsi_clock_info *cinfo = &dsi->current_cinfo;
+       struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
        enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
        int dsi_module = dsi->module_id;
+       struct dss_pll *pll = &dsi->pll;
 
        dispc_clk_src = dss_get_dispc_clk_source();
        dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
@@ -1759,28 +1495,28 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
 
        seq_printf(s,   "- DSI%d PLL -\n", dsi_module + 1);
 
-       seq_printf(s,   "dsi pll clkin\t%lu\n", cinfo->clkin);
+       seq_printf(s,   "dsi pll clkin\t%lu\n", clk_get_rate(pll->clkin));
 
-       seq_printf(s,   "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
+       seq_printf(s,   "Fint\t\t%-16lun %u\n", cinfo->fint, cinfo->n);
 
-       seq_printf(s,   "CLKIN4DDR\t%-16luregm %u\n",
-                       cinfo->clkin4ddr, cinfo->regm);
+       seq_printf(s,   "CLKIN4DDR\t%-16lum %u\n",
+                       cinfo->clkdco, cinfo->m);
 
-       seq_printf(s,   "DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n",
+       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),
-                       cinfo->dsi_pll_hsdiv_dispc_clk,
-                       cinfo->regm_dispc,
+                       cinfo->clkout[HSDIV_DISPC],
+                       cinfo->mX[HSDIV_DISPC],
                        dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
                        "off" : "on");
 
-       seq_printf(s,   "DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n",
+       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),
-                       cinfo->dsi_pll_hsdiv_dsi_clk,
-                       cinfo->regm_dsi,
+                       cinfo->clkout[HSDIV_DSI],
+                       cinfo->mX[HSDIV_DSI],
                        dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
                        "off" : "on");
 
@@ -1793,11 +1529,11 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
        seq_printf(s,   "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
 
        seq_printf(s,   "DDR_CLK\t\t%lu\n",
-                       cinfo->clkin4ddr / 4);
+                       cinfo->clkdco / 4);
 
        seq_printf(s,   "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev));
 
-       seq_printf(s,   "LP_CLK\t\t%lu\n", cinfo->lp_clk);
+       seq_printf(s,   "LP_CLK\t\t%lu\n", dsi->current_lp_cinfo.lp_clk);
 
        dsi_runtime_put(dsidev);
 }
@@ -2132,7 +1868,7 @@ static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        /* convert time in ns to ddr ticks, rounding up */
-       unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
+       unsigned long ddr_clk = dsi->pll.cinfo.clkdco / 4;
        return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000;
 }
 
@@ -2140,7 +1876,7 @@ static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
-       unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
+       unsigned long ddr_clk = dsi->pll.cinfo.clkdco / 4;
        return ddr * 1000 * 1000 / (ddr_clk / 1000);
 }
 
@@ -3730,7 +3466,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
        struct omap_video_timings *timings = &dsi->timings;
        int bpp = dsi_get_pixel_size(dsi->pix_fmt);
        int ndl = dsi->num_lanes_used - 1;
-       int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.regm_dsi + 1;
+       int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1;
        int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
        int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
        int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
@@ -4441,18 +4177,12 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
 static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       struct dsi_clock_info cinfo;
+       struct dss_pll_clock_info cinfo;
        int r;
 
        cinfo = dsi->user_dsi_cinfo;
 
-       r = dsi_calc_clock_rates(dsidev, &cinfo);
-       if (r) {
-               DSSERR("Failed to calc dsi clocks\n");
-               return r;
-       }
-
-       r = dsi_pll_set_clock_div(dsidev, &cinfo);
+       r = dss_pll_set_config(&dsi->pll, &cinfo);
        if (r) {
                DSSERR("Failed to set dsi clocks\n");
                return r;
@@ -4466,7 +4196,7 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        int r;
 
-       r = dsi_pll_init(dsidev, true, true);
+       r = dss_pll_enable(&dsi->pll);
        if (r)
                goto err0;
 
@@ -4510,7 +4240,7 @@ err3:
 err2:
        dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
 err1:
-       dsi_pll_uninit(dsidev, true);
+       dss_pll_disable(&dsi->pll);
 err0:
        return r;
 }
@@ -4551,8 +4281,6 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err_get_dsi;
 
-       dsi_enable_pll_clock(dsidev, 1);
-
        _dsi_initialize_irq(dsidev);
 
        r = dsi_display_init_dsi(dsidev);
@@ -4564,7 +4292,6 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
        return 0;
 
 err_init_dsi:
-       dsi_enable_pll_clock(dsidev, 0);
        dsi_runtime_put(dsidev);
 err_get_dsi:
        mutex_unlock(&dsi->lock);
@@ -4592,7 +4319,6 @@ static void dsi_display_disable(struct omap_dss_device *dssdev,
        dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps);
 
        dsi_runtime_put(dsidev);
-       dsi_enable_pll_clock(dsidev, 0);
 
        mutex_unlock(&dsi->lock);
 }
@@ -4713,29 +4439,30 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
        return true;
 }
 
-static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+static bool dsi_cm_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
                void *data)
 {
        struct dsi_clk_calc_ctx *ctx = data;
 
-       ctx->dsi_cinfo.regm_dispc = regm_dispc;
-       ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+       ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc;
+       ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc;
 
        return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
                        dsi_cm_calc_dispc_cb, ctx);
 }
 
-static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
-               unsigned long pll, void *data)
+static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
+               unsigned long clkdco, void *data)
 {
        struct dsi_clk_calc_ctx *ctx = data;
 
-       ctx->dsi_cinfo.regn = regn;
-       ctx->dsi_cinfo.regm = regm;
+       ctx->dsi_cinfo.n = n;
+       ctx->dsi_cinfo.m = m;
        ctx->dsi_cinfo.fint = fint;
-       ctx->dsi_cinfo.clkin4ddr = pll;
+       ctx->dsi_cinfo.clkdco = clkdco;
 
-       return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+       return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min,
+                       dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
                        dsi_cm_calc_hsdiv_cb, ctx);
 }
 
@@ -4748,7 +4475,7 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
        unsigned long pll_min, pll_max;
        unsigned long pck, txbyteclk;
 
-       clkin = clk_get_rate(dsi->sys_clk);
+       clkin = clk_get_rate(dsi->pll.clkin);
        bitspp = dsi_get_pixel_size(cfg->pixel_format);
        ndl = dsi->num_lanes_used - 1;
 
@@ -4764,16 +4491,16 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
 
        memset(ctx, 0, sizeof(*ctx));
        ctx->dsidev = dsi->pdev;
+       ctx->pll = &dsi->pll;
        ctx->config = cfg;
        ctx->req_pck_min = pck;
        ctx->req_pck_nom = pck;
        ctx->req_pck_max = pck * 3 / 2;
-       ctx->dsi_cinfo.clkin = clkin;
 
        pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
        pll_max = cfg->hs_clk_max * 4;
 
-       return dsi_pll_calc(dsi->pdev, clkin,
+       return dss_pll_calc(ctx->pll, clkin,
                        pll_min, pll_max,
                        dsi_cm_calc_pll_cb, ctx);
 }
@@ -4784,7 +4511,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
        const struct omap_dss_dsi_config *cfg = ctx->config;
        int bitspp = dsi_get_pixel_size(cfg->pixel_format);
        int ndl = dsi->num_lanes_used - 1;
-       unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
+       unsigned long hsclk = ctx->dsi_cinfo.clkdco / 4;
        unsigned long byteclk = hsclk / 4;
 
        unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
@@ -4999,14 +4726,14 @@ static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
        return true;
 }
 
-static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+static bool dsi_vm_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
                void *data)
 {
        struct dsi_clk_calc_ctx *ctx = data;
        unsigned long pck_max;
 
-       ctx->dsi_cinfo.regm_dispc = regm_dispc;
-       ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+       ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc;
+       ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc;
 
        /*
         * In burst mode we can let the dispc pck be arbitrarily high, but it
@@ -5022,17 +4749,18 @@ static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
                        dsi_vm_calc_dispc_cb, ctx);
 }
 
-static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
-               unsigned long pll, void *data)
+static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
+               unsigned long clkdco, void *data)
 {
        struct dsi_clk_calc_ctx *ctx = data;
 
-       ctx->dsi_cinfo.regn = regn;
-       ctx->dsi_cinfo.regm = regm;
+       ctx->dsi_cinfo.n = n;
+       ctx->dsi_cinfo.m = m;
        ctx->dsi_cinfo.fint = fint;
-       ctx->dsi_cinfo.clkin4ddr = pll;
+       ctx->dsi_cinfo.clkdco = clkdco;
 
-       return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+       return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min,
+                       dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
                        dsi_vm_calc_hsdiv_cb, ctx);
 }
 
@@ -5048,14 +4776,13 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
        int bitspp = dsi_get_pixel_size(cfg->pixel_format);
        unsigned long byteclk_min;
 
-       clkin = clk_get_rate(dsi->sys_clk);
+       clkin = clk_get_rate(dsi->pll.clkin);
 
        memset(ctx, 0, sizeof(*ctx));
        ctx->dsidev = dsi->pdev;
+       ctx->pll = &dsi->pll;
        ctx->config = cfg;
 
-       ctx->dsi_cinfo.clkin = clkin;
-
        /* these limits should come from the panel driver */
        ctx->req_pck_min = t->pixelclock - 1000;
        ctx->req_pck_nom = t->pixelclock;
@@ -5074,7 +4801,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
                pll_max = byteclk_max * 4 * 4;
        }
 
-       return dsi_pll_calc(dsi->pdev, clkin,
+       return dss_pll_calc(ctx->pll, clkin,
                        pll_min, pll_max,
                        dsi_vm_calc_pll_cb, ctx);
 }
@@ -5106,8 +4833,8 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
 
        dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
 
-       r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
-                       config->lp_clk_max);
+       r = dsi_lp_clock_calc(ctx.dsi_cinfo.clkout[HSDIV_DSI],
+               config->lp_clk_min, config->lp_clk_max, &dsi->user_lp_cinfo);
        if (r) {
                DSSERR("failed to find suitable DSI LP clock settings\n");
                goto err;
@@ -5234,35 +4961,6 @@ static void dsi_release_vc(struct omap_dss_device *dssdev, int channel)
        }
 }
 
-void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
-{
-       if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 7, 1) != 1)
-               DSSERR("%s (%s) not active\n",
-                       dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
-                       dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
-}
-
-void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
-{
-       if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 8, 1) != 1)
-               DSSERR("%s (%s) not active\n",
-                       dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
-                       dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
-}
-
-static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
-{
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-       dsi->regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
-       dsi->regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
-       dsi->regm_dispc_max =
-               dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
-       dsi->regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
-       dsi->fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
-       dsi->fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
-       dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
-}
 
 static int dsi_get_clocks(struct platform_device *dsidev)
 {
@@ -5277,14 +4975,6 @@ static int dsi_get_clocks(struct platform_device *dsidev)
 
        dsi->dss_clk = clk;
 
-       clk = devm_clk_get(&dsidev->dev, "sys_clk");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get sys_clk\n");
-               return PTR_ERR(clk);
-       }
-
-       dsi->sys_clk = clk;
-
        return 0;
 }
 
@@ -5453,6 +5143,135 @@ err:
        return r;
 }
 
+static const struct dss_pll_ops dsi_pll_ops = {
+       .enable = dsi_pll_enable,
+       .disable = dsi_pll_disable,
+       .set_config = dss_pll_write_config_type_a,
+};
+
+static const struct dss_pll_hw dss_omap3_dsi_pll_hw = {
+       .n_max = (1 << 7) - 1,
+       .m_max = (1 << 11) - 1,
+       .mX_max = (1 << 4) - 1,
+       .fint_min = 750000,
+       .fint_max = 2100000,
+       .clkdco_low = 1000000000,
+       .clkdco_max = 1800000000,
+
+       .n_msb = 7,
+       .n_lsb = 1,
+       .m_msb = 18,
+       .m_lsb = 8,
+
+       .mX_msb[0] = 22,
+       .mX_lsb[0] = 19,
+       .mX_msb[1] = 26,
+       .mX_lsb[1] = 23,
+
+       .has_stopmode = true,
+       .has_freqsel = true,
+       .has_selfreqdco = false,
+       .has_refsel = false,
+};
+
+static const struct dss_pll_hw dss_omap4_dsi_pll_hw = {
+       .n_max = (1 << 8) - 1,
+       .m_max = (1 << 12) - 1,
+       .mX_max = (1 << 5) - 1,
+       .fint_min = 500000,
+       .fint_max = 2500000,
+       .clkdco_low = 1000000000,
+       .clkdco_max = 1800000000,
+
+       .n_msb = 8,
+       .n_lsb = 1,
+       .m_msb = 20,
+       .m_lsb = 9,
+
+       .mX_msb[0] = 25,
+       .mX_lsb[0] = 21,
+       .mX_msb[1] = 30,
+       .mX_lsb[1] = 26,
+
+       .has_stopmode = true,
+       .has_freqsel = false,
+       .has_selfreqdco = false,
+       .has_refsel = false,
+};
+
+static const struct dss_pll_hw dss_omap5_dsi_pll_hw = {
+       .n_max = (1 << 8) - 1,
+       .m_max = (1 << 12) - 1,
+       .mX_max = (1 << 5) - 1,
+       .fint_min = 150000,
+       .fint_max = 52000000,
+       .clkdco_low = 1000000000,
+       .clkdco_max = 1800000000,
+
+       .n_msb = 8,
+       .n_lsb = 1,
+       .m_msb = 20,
+       .m_lsb = 9,
+
+       .mX_msb[0] = 25,
+       .mX_lsb[0] = 21,
+       .mX_msb[1] = 30,
+       .mX_lsb[1] = 26,
+
+       .has_stopmode = true,
+       .has_freqsel = false,
+       .has_selfreqdco = true,
+       .has_refsel = true,
+};
+
+static int dsi_init_pll_data(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct dss_pll *pll = &dsi->pll;
+       struct clk *clk;
+       int r;
+
+       clk = devm_clk_get(&dsidev->dev, "sys_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get sys_clk\n");
+               return PTR_ERR(clk);
+       }
+
+       pll->name = dsi->module_id == 0 ? "dsi0" : "dsi1";
+       pll->clkin = clk;
+       pll->base = dsi->pll_base;
+
+       switch (omapdss_get_version()) {
+       case OMAPDSS_VER_OMAP34xx_ES1:
+       case OMAPDSS_VER_OMAP34xx_ES3:
+       case OMAPDSS_VER_OMAP3630:
+       case OMAPDSS_VER_AM35xx:
+               pll->hw = &dss_omap3_dsi_pll_hw;
+               break;
+
+       case OMAPDSS_VER_OMAP4430_ES1:
+       case OMAPDSS_VER_OMAP4430_ES2:
+       case OMAPDSS_VER_OMAP4:
+               pll->hw = &dss_omap4_dsi_pll_hw;
+               break;
+
+       case OMAPDSS_VER_OMAP5:
+               pll->hw = &dss_omap5_dsi_pll_hw;
+               break;
+
+       default:
+               return -ENODEV;
+       }
+
+       pll->ops = &dsi_pll_ops;
+
+       r = dss_pll_register(pll);
+       if (r)
+               return r;
+
+       return 0;
+}
+
 /* DSI1 HW IP initialisation */
 static int omap_dsihw_probe(struct platform_device *dsidev)
 {
@@ -5598,12 +5417,12 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
                dsi->vc[i].vc_id = 0;
        }
 
-       dsi_calc_clock_param_ranges(dsidev);
-
        r = dsi_get_clocks(dsidev);
        if (r)
                return r;
 
+       dsi_init_pll_data(dsidev);
+
        pm_runtime_enable(&dsidev->dev);
 
        r = dsi_runtime_get(dsidev);
@@ -5672,6 +5491,8 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
 
        WARN_ON(dsi->scp_clk_refcount > 0);
 
+       dss_pll_unregister(&dsi->pll);
+
        dsi_uninit_output(dsidev);
 
        pm_runtime_disable(&dsidev->dev);
index a4b20aaf61428c08f8747582ce0d90fa4c6cb377..928ee639c0c19ba3a2346737c41b44f38e82c0b5 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <video/omapdss.h>
 
+#include "dss.h"
+
 struct device_node *
 omapdss_of_get_next_port(const struct device_node *parent,
                         struct device_node *prev)
@@ -84,20 +86,17 @@ omapdss_of_get_next_endpoint(const struct device_node *parent,
 }
 EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint);
 
-static struct device_node *
-omapdss_of_get_remote_device_node(const struct device_node *node)
+struct device_node *dss_of_port_get_parent_device(struct device_node *port)
 {
        struct device_node *np;
        int i;
 
-       np = of_parse_phandle(node, "remote-endpoint", 0);
-
-       if (!np)
+       if (!port)
                return NULL;
 
-       np = of_get_next_parent(np);
+       np = of_get_next_parent(port);
 
-       for (i = 0; i < 3 && np; ++i) {
+       for (i = 0; i < 2 && np; ++i) {
                struct property *prop;
 
                prop = of_find_property(np, "compatible", NULL);
@@ -111,6 +110,31 @@ omapdss_of_get_remote_device_node(const struct device_node *node)
        return NULL;
 }
 
+u32 dss_of_port_get_port_number(struct device_node *port)
+{
+       int r;
+       u32 reg;
+
+       r = of_property_read_u32(port, "reg", &reg);
+       if (r)
+               reg = 0;
+
+       return reg;
+}
+
+static struct device_node *omapdss_of_get_remote_port(const struct device_node *node)
+{
+       struct device_node *np;
+
+       np = of_parse_phandle(node, "remote-endpoint", 0);
+       if (!np)
+               return NULL;
+
+       np = of_get_next_parent(np);
+
+       return np;
+}
+
 struct device_node *
 omapdss_of_get_first_endpoint(const struct device_node *parent)
 {
@@ -133,27 +157,25 @@ struct omap_dss_device *
 omapdss_of_find_source_for_first_ep(struct device_node *node)
 {
        struct device_node *ep;
-       struct device_node *src_node;
+       struct device_node *src_port;
        struct omap_dss_device *src;
 
        ep = omapdss_of_get_first_endpoint(node);
        if (!ep)
                return ERR_PTR(-EINVAL);
 
-       src_node = omapdss_of_get_remote_device_node(ep);
-
-       of_node_put(ep);
-
-       if (!src_node)
+       src_port = omapdss_of_get_remote_port(ep);
+       if (!src_port) {
+               of_node_put(ep);
                return ERR_PTR(-EINVAL);
+       }
 
-       src = omap_dss_find_output_by_node(src_node);
+       of_node_put(ep);
 
-       of_node_put(src_node);
+       src = omap_dss_find_output_by_port_node(src_port);
 
-       if (!src)
-               return ERR_PTR(-EPROBE_DEFER);
+       of_node_put(src_port);
 
-       return src;
+       return src ? src : ERR_PTR(-EPROBE_DEFER);
 }
 EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep);
index 14bcd6c43f726d6c9e6c88baa2880f80bf8c97b5..702c495083eda24fdee724fb393afbc15b6c6cb5 100644 (file)
@@ -70,7 +70,9 @@ struct dss_features {
        u8 fck_div_max;
        u8 dss_fck_multiplier;
        const char *parent_clk_name;
-       int (*dpi_select_source)(enum omap_channel channel);
+       enum omap_display_type *ports;
+       int num_ports;
+       int (*dpi_select_source)(int port, enum omap_channel channel);
 };
 
 static struct {
@@ -294,7 +296,6 @@ static void dss_dump_regs(struct seq_file *s)
 
 static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
 {
-       struct platform_device *dsidev;
        int b;
        u8 start, end;
 
@@ -304,13 +305,9 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
                break;
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
                b = 1;
-               dsidev = dsi_get_dsidev_from_id(0);
-               dsi_wait_pll_hsdiv_dispc_active(dsidev);
                break;
        case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
                b = 2;
-               dsidev = dsi_get_dsidev_from_id(1);
-               dsi_wait_pll_hsdiv_dispc_active(dsidev);
                break;
        default:
                BUG();
@@ -327,7 +324,6 @@ 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)
 {
-       struct platform_device *dsidev;
        int b, pos;
 
        switch (clk_src) {
@@ -337,14 +333,10 @@ void dss_select_dsi_clk_source(int dsi_module,
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
                BUG_ON(dsi_module != 0);
                b = 1;
-               dsidev = dsi_get_dsidev_from_id(0);
-               dsi_wait_pll_hsdiv_dsi_active(dsidev);
                break;
        case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
                BUG_ON(dsi_module != 1);
                b = 1;
-               dsidev = dsi_get_dsidev_from_id(1);
-               dsi_wait_pll_hsdiv_dsi_active(dsidev);
                break;
        default:
                BUG();
@@ -360,7 +352,6 @@ void dss_select_dsi_clk_source(int dsi_module,
 void dss_select_lcd_clk_source(enum omap_channel channel,
                enum omap_dss_clk_source clk_src)
 {
-       struct platform_device *dsidev;
        int b, ix, pos;
 
        if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
@@ -375,15 +366,11 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
                BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
                b = 1;
-               dsidev = dsi_get_dsidev_from_id(0);
-               dsi_wait_pll_hsdiv_dispc_active(dsidev);
                break;
        case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
                BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
                       channel != OMAP_DSS_CHANNEL_LCD3);
                b = 1;
-               dsidev = dsi_get_dsidev_from_id(1);
-               dsi_wait_pll_hsdiv_dispc_active(dsidev);
                break;
        default:
                BUG();
@@ -564,7 +551,7 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
        return REG_GET(DSS_CONTROL, 15, 15);
 }
 
-static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
+static int dss_dpi_select_source_omap2_omap3(int port, enum omap_channel channel)
 {
        if (channel != OMAP_DSS_CHANNEL_LCD)
                return -EINVAL;
@@ -572,7 +559,7 @@ static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
        return 0;
 }
 
-static int dss_dpi_select_source_omap4(enum omap_channel channel)
+static int dss_dpi_select_source_omap4(int port, enum omap_channel channel)
 {
        int val;
 
@@ -592,7 +579,7 @@ static int dss_dpi_select_source_omap4(enum omap_channel channel)
        return 0;
 }
 
-static int dss_dpi_select_source_omap5(enum omap_channel channel)
+static int dss_dpi_select_source_omap5(int port, enum omap_channel channel)
 {
        int val;
 
@@ -618,9 +605,9 @@ static int dss_dpi_select_source_omap5(enum omap_channel channel)
        return 0;
 }
 
-int dss_dpi_select_source(enum omap_channel channel)
+int dss_dpi_select_source(int port, enum omap_channel channel)
 {
-       return dss.feat->dpi_select_source(channel);
+       return dss.feat->dpi_select_source(port, channel);
 }
 
 static int dss_get_clocks(void)
@@ -689,6 +676,16 @@ void dss_debug_dump_clocks(struct seq_file *s)
 }
 #endif
 
+
+static enum omap_display_type omap2plus_ports[] = {
+       OMAP_DISPLAY_TYPE_DPI,
+};
+
+static enum omap_display_type omap34xx_ports[] = {
+       OMAP_DISPLAY_TYPE_DPI,
+       OMAP_DISPLAY_TYPE_SDI,
+};
+
 static const struct dss_features omap24xx_dss_feats __initconst = {
        /*
         * fck div max is really 16, but the divider range has gaps. The range
@@ -698,6 +695,8 @@ static const struct dss_features omap24xx_dss_feats __initconst = {
        .dss_fck_multiplier     =       2,
        .parent_clk_name        =       "core_ck",
        .dpi_select_source      =       &dss_dpi_select_source_omap2_omap3,
+       .ports                  =       omap2plus_ports,
+       .num_ports              =       ARRAY_SIZE(omap2plus_ports),
 };
 
 static const struct dss_features omap34xx_dss_feats __initconst = {
@@ -705,6 +704,8 @@ static const struct dss_features omap34xx_dss_feats __initconst = {
        .dss_fck_multiplier     =       2,
        .parent_clk_name        =       "dpll4_ck",
        .dpi_select_source      =       &dss_dpi_select_source_omap2_omap3,
+       .ports                  =       omap34xx_ports,
+       .num_ports              =       ARRAY_SIZE(omap34xx_ports),
 };
 
 static const struct dss_features omap3630_dss_feats __initconst = {
@@ -712,6 +713,8 @@ static const struct dss_features omap3630_dss_feats __initconst = {
        .dss_fck_multiplier     =       1,
        .parent_clk_name        =       "dpll4_ck",
        .dpi_select_source      =       &dss_dpi_select_source_omap2_omap3,
+       .ports                  =       omap2plus_ports,
+       .num_ports              =       ARRAY_SIZE(omap2plus_ports),
 };
 
 static const struct dss_features omap44xx_dss_feats __initconst = {
@@ -719,6 +722,8 @@ static const struct dss_features omap44xx_dss_feats __initconst = {
        .dss_fck_multiplier     =       1,
        .parent_clk_name        =       "dpll_per_x2_ck",
        .dpi_select_source      =       &dss_dpi_select_source_omap4,
+       .ports                  =       omap2plus_ports,
+       .num_ports              =       ARRAY_SIZE(omap2plus_ports),
 };
 
 static const struct dss_features omap54xx_dss_feats __initconst = {
@@ -726,6 +731,8 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
        .dss_fck_multiplier     =       1,
        .parent_clk_name        =       "dpll_per_x2_ck",
        .dpi_select_source      =       &dss_dpi_select_source_omap5,
+       .ports                  =       omap2plus_ports,
+       .num_ports              =       ARRAY_SIZE(omap2plus_ports),
 };
 
 static const struct dss_features am43xx_dss_feats __initconst = {
@@ -733,6 +740,8 @@ static const struct dss_features am43xx_dss_feats __initconst = {
        .dss_fck_multiplier     =       0,
        .parent_clk_name        =       NULL,
        .dpi_select_source      =       &dss_dpi_select_source_omap2_omap3,
+       .ports                  =       omap2plus_ports,
+       .num_ports              =       ARRAY_SIZE(omap2plus_ports),
 };
 
 static int __init dss_init_features(struct platform_device *pdev)
@@ -798,37 +807,77 @@ static int __init dss_init_ports(struct platform_device *pdev)
        if (!port)
                return 0;
 
+       if (dss.feat->num_ports == 0)
+               return 0;
+
        do {
+               enum omap_display_type port_type;
                u32 reg;
 
                r = of_property_read_u32(port, "reg", &reg);
                if (r)
                        reg = 0;
 
-#ifdef CONFIG_OMAP2_DSS_DPI
-               if (reg == 0)
-                       dpi_init_port(pdev, port);
-#endif
+               if (reg >= dss.feat->num_ports)
+                       continue;
 
-#ifdef CONFIG_OMAP2_DSS_SDI
-               if (reg == 1)
-                       sdi_init_port(pdev, port);
-#endif
+               port_type = dss.feat->ports[reg];
 
+               switch (port_type) {
+               case OMAP_DISPLAY_TYPE_DPI:
+                       dpi_init_port(pdev, port);
+                       break;
+               case OMAP_DISPLAY_TYPE_SDI:
+                       sdi_init_port(pdev, port);
+                       break;
+               default:
+                       break;
+               }
        } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
 
        return 0;
 }
 
-static void __exit dss_uninit_ports(void)
+static void __exit dss_uninit_ports(struct platform_device *pdev)
 {
-#ifdef CONFIG_OMAP2_DSS_DPI
-       dpi_uninit_port();
-#endif
+       struct device_node *parent = pdev->dev.of_node;
+       struct device_node *port;
 
-#ifdef CONFIG_OMAP2_DSS_SDI
-       sdi_uninit_port();
-#endif
+       if (parent == NULL)
+               return;
+
+       port = omapdss_of_get_next_port(parent, NULL);
+       if (!port)
+               return;
+
+       if (dss.feat->num_ports == 0)
+               return;
+
+       do {
+               enum omap_display_type port_type;
+               u32 reg;
+               int r;
+
+               r = of_property_read_u32(port, "reg", &reg);
+               if (r)
+                       reg = 0;
+
+               if (reg >= dss.feat->num_ports)
+                       continue;
+
+               port_type = dss.feat->ports[reg];
+
+               switch (port_type) {
+               case OMAP_DISPLAY_TYPE_DPI:
+                       dpi_uninit_port(port);
+                       break;
+               case OMAP_DISPLAY_TYPE_SDI:
+                       sdi_uninit_port(port);
+                       break;
+               default:
+                       break;
+               }
+       } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
 }
 
 /* DSS HW IP initialisation */
@@ -910,7 +959,7 @@ err_setup_clocks:
 
 static int __exit omap_dsshw_remove(struct platform_device *pdev)
 {
-       dss_uninit_ports();
+       dss_uninit_ports(pdev);
 
        pm_runtime_disable(&pdev->dev);
 
index 8ff22c134c6293161247690d26ab991a34a40767..14fb0c23f4a258e6869c4999f17e8afeb14cd348 100644 (file)
@@ -100,35 +100,77 @@ enum dss_writeback_channel {
        DSS_WB_LCD3_MGR =       7,
 };
 
-struct dispc_clock_info {
+struct dss_pll;
+
+#define DSS_PLL_MAX_HSDIVS 4
+
+/*
+ * Type-A PLLs: clkout[]/mX[] refer to hsdiv outputs m4, m5, m6, m7.
+ * Type-B PLLs: clkout[0] refers to m2.
+ */
+struct dss_pll_clock_info {
        /* rates that we get with dividers below */
-       unsigned long lck;
-       unsigned long pck;
+       unsigned long fint;
+       unsigned long clkdco;
+       unsigned long clkout[DSS_PLL_MAX_HSDIVS];
 
        /* dividers */
-       u16 lck_div;
-       u16 pck_div;
+       u16 n;
+       u16 m;
+       u32 mf;
+       u16 mX[DSS_PLL_MAX_HSDIVS];
+       u16 sd;
+};
+
+struct dss_pll_ops {
+       int (*enable)(struct dss_pll *pll);
+       void (*disable)(struct dss_pll *pll);
+       int (*set_config)(struct dss_pll *pll,
+               const struct dss_pll_clock_info *cinfo);
+};
+
+struct dss_pll_hw {
+       unsigned n_max;
+       unsigned m_min;
+       unsigned m_max;
+       unsigned mX_max;
+
+       unsigned long fint_min, fint_max;
+       unsigned long clkdco_min, clkdco_low, clkdco_max;
+
+       u8 n_msb, n_lsb;
+       u8 m_msb, m_lsb;
+       u8 mX_msb[DSS_PLL_MAX_HSDIVS], mX_lsb[DSS_PLL_MAX_HSDIVS];
+
+       bool has_stopmode;
+       bool has_freqsel;
+       bool has_selfreqdco;
+       bool has_refsel;
 };
 
-struct dsi_clock_info {
+struct dss_pll {
+       const char *name;
+
+       struct clk *clkin;
+       struct regulator *regulator;
+
+       void __iomem *base;
+
+       const struct dss_pll_hw *hw;
+
+       const struct dss_pll_ops *ops;
+
+       struct dss_pll_clock_info cinfo;
+};
+
+struct dispc_clock_info {
        /* rates that we get with dividers below */
-       unsigned long fint;
-       unsigned long clkin4ddr;
-       unsigned long clkin;
-       unsigned long dsi_pll_hsdiv_dispc_clk;  /* OMAP3: DSI1_PLL_CLK
-                                                * OMAP4: PLLx_CLK1 */
-       unsigned long dsi_pll_hsdiv_dsi_clk;    /* OMAP3: DSI2_PLL_CLK
-                                                * OMAP4: PLLx_CLK2 */
-       unsigned long lp_clk;
+       unsigned long lck;
+       unsigned long pck;
 
        /* dividers */
-       u16 regn;
-       u16 regm;
-       u16 regm_dispc; /* OMAP3: REGM3
-                        * OMAP4: REGM4 */
-       u16 regm_dsi;   /* OMAP3: REGM4
-                        * OMAP4: REGM5 */
-       u16 lp_clk_div;
+       u16 lck_div;
+       u16 pck_div;
 };
 
 struct dss_lcd_mgr_config {
@@ -209,12 +251,16 @@ int dss_init_platform_driver(void) __init;
 void dss_uninit_platform_driver(void);
 
 unsigned long dss_get_dispc_clk_rate(void);
-int dss_dpi_select_source(enum omap_channel channel);
+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);
 void dss_dump_clocks(struct seq_file *s);
 
+/* dss-of */
+struct device_node *dss_of_port_get_parent_device(struct device_node *port);
+u32 dss_of_port_get_port_number(struct device_node *port);
+
 #if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 void dss_debug_dump_clocks(struct seq_file *s);
 #endif
@@ -244,16 +290,22 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
 int sdi_init_platform_driver(void) __init;
 void sdi_uninit_platform_driver(void) __exit;
 
+#ifdef CONFIG_OMAP2_DSS_SDI
 int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init;
-void sdi_uninit_port(void) __exit;
+void sdi_uninit_port(struct device_node *port) __exit;
+#else
+static inline int __init sdi_init_port(struct platform_device *pdev,
+               struct device_node *port)
+{
+       return 0;
+}
+static inline void __exit sdi_uninit_port(struct device_node *port)
+{
+}
+#endif
 
 /* DSI */
 
-typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
-               unsigned long pll, void *data);
-typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
-               void *data);
-
 #ifdef CONFIG_OMAP2_DSS_DSI
 
 struct dentry;
@@ -262,104 +314,36 @@ struct file_operations;
 int dsi_init_platform_driver(void) __init;
 void dsi_uninit_platform_driver(void) __exit;
 
-int dsi_runtime_get(struct platform_device *dsidev);
-void dsi_runtime_put(struct platform_device *dsidev);
-
 void dsi_dump_clocks(struct seq_file *s);
 
 void dsi_irq_handler(void);
 u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
 
-unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
-
-bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
-               unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
-bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
-               unsigned long pll_min, unsigned long pll_max,
-               dsi_pll_calc_func func, void *data);
-
-unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
-int dsi_pll_set_clock_div(struct platform_device *dsidev,
-               struct dsi_clock_info *cinfo);
-int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
-               bool enable_hsdiv);
-void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
-void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
-void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
-struct platform_device *dsi_get_dsidev_from_id(int module);
 #else
-static inline int dsi_runtime_get(struct platform_device *dsidev)
-{
-       return 0;
-}
-static inline void dsi_runtime_put(struct platform_device *dsidev)
-{
-}
 static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
 {
        WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
        return 0;
 }
-static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
-{
-       WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
-       return 0;
-}
-static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
-               struct dsi_clock_info *cinfo)
-{
-       WARN("%s: DSI not compiled in\n", __func__);
-       return -ENODEV;
-}
-static inline int dsi_pll_init(struct platform_device *dsidev,
-               bool enable_hsclk, bool enable_hsdiv)
-{
-       WARN("%s: DSI not compiled in\n", __func__);
-       return -ENODEV;
-}
-static inline void dsi_pll_uninit(struct platform_device *dsidev,
-               bool disconnect_lanes)
-{
-}
-static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
-{
-}
-static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
-{
-}
-static inline struct platform_device *dsi_get_dsidev_from_id(int module)
-{
-       return NULL;
-}
-
-static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
-{
-       return 0;
-}
-
-static inline bool dsi_hsdiv_calc(struct platform_device *dsidev,
-               unsigned long pll, unsigned long out_min,
-               dsi_hsdiv_calc_func func, void *data)
-{
-       return false;
-}
-
-static inline bool dsi_pll_calc(struct platform_device *dsidev,
-               unsigned long clkin,
-               unsigned long pll_min, unsigned long pll_max,
-               dsi_pll_calc_func func, void *data)
-{
-       return false;
-}
-
 #endif
 
 /* DPI */
 int dpi_init_platform_driver(void) __init;
 void dpi_uninit_platform_driver(void) __exit;
 
+#ifdef CONFIG_OMAP2_DSS_DPI
 int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init;
-void dpi_uninit_port(void) __exit;
+void dpi_uninit_port(struct device_node *port) __exit;
+#else
+static inline int __init dpi_init_port(struct platform_device *pdev,
+               struct device_node *port)
+{
+       return 0;
+}
+static inline void __exit dpi_uninit_port(struct device_node *port)
+{
+}
+#endif
 
 /* DISPC */
 int dispc_init_platform_driver(void) __init;
@@ -438,4 +422,29 @@ static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr)
 }
 #endif
 
+/* PLL */
+typedef bool (*dss_pll_calc_func)(int n, int m, unsigned long fint,
+               unsigned long clkdco, void *data);
+typedef bool (*dss_hsdiv_calc_func)(int m_dispc, unsigned long dispc,
+               void *data);
+
+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);
+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,
+               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,
+               unsigned long pll_min, unsigned long pll_max,
+               dss_pll_calc_func func, void *data);
+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,
+               const struct dss_pll_clock_info *cinfo);
+
 #endif
index 15088df7bd16e1437773b77213490f00fd337fdb..0e3da809473cf8379d9c7b95278864a5ac6ae162 100644 (file)
@@ -72,10 +72,6 @@ static const struct dss_reg_field omap2_dss_reg_fields[] = {
        [FEAT_REG_HORIZONTALACCU]               = { 9, 0 },
        [FEAT_REG_VERTICALACCU]                 = { 25, 16 },
        [FEAT_REG_DISPC_CLK_SWITCH]             = { 0, 0 },
-       [FEAT_REG_DSIPLL_REGN]                  = { 0, 0 },
-       [FEAT_REG_DSIPLL_REGM]                  = { 0, 0 },
-       [FEAT_REG_DSIPLL_REGM_DISPC]            = { 0, 0 },
-       [FEAT_REG_DSIPLL_REGM_DSI]              = { 0, 0 },
 };
 
 static const struct dss_reg_field omap3_dss_reg_fields[] = {
@@ -87,10 +83,6 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = {
        [FEAT_REG_HORIZONTALACCU]               = { 9, 0 },
        [FEAT_REG_VERTICALACCU]                 = { 25, 16 },
        [FEAT_REG_DISPC_CLK_SWITCH]             = { 0, 0 },
-       [FEAT_REG_DSIPLL_REGN]                  = { 7, 1 },
-       [FEAT_REG_DSIPLL_REGM]                  = { 18, 8 },
-       [FEAT_REG_DSIPLL_REGM_DISPC]            = { 22, 19 },
-       [FEAT_REG_DSIPLL_REGM_DSI]              = { 26, 23 },
 };
 
 static const struct dss_reg_field am43xx_dss_reg_fields[] = {
@@ -113,10 +105,6 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
        [FEAT_REG_HORIZONTALACCU]               = { 10, 0 },
        [FEAT_REG_VERTICALACCU]                 = { 26, 16 },
        [FEAT_REG_DISPC_CLK_SWITCH]             = { 9, 8 },
-       [FEAT_REG_DSIPLL_REGN]                  = { 8, 1 },
-       [FEAT_REG_DSIPLL_REGM]                  = { 20, 9 },
-       [FEAT_REG_DSIPLL_REGM_DISPC]            = { 25, 21 },
-       [FEAT_REG_DSIPLL_REGM_DSI]              = { 30, 26 },
 };
 
 static const struct dss_reg_field omap5_dss_reg_fields[] = {
@@ -128,10 +116,6 @@ static const struct dss_reg_field omap5_dss_reg_fields[] = {
        [FEAT_REG_HORIZONTALACCU]               = { 10, 0 },
        [FEAT_REG_VERTICALACCU]                 = { 26, 16 },
        [FEAT_REG_DISPC_CLK_SWITCH]             = { 9, 7 },
-       [FEAT_REG_DSIPLL_REGN]                  = { 8, 1 },
-       [FEAT_REG_DSIPLL_REGM]                  = { 20, 9 },
-       [FEAT_REG_DSIPLL_REGM_DISPC]            = { 25, 21 },
-       [FEAT_REG_DSIPLL_REGM_DSI]              = { 30, 26 },
 };
 
 static const enum omap_display_type omap2_dss_supported_displays[] = {
@@ -437,12 +421,6 @@ static const char * const omap5_dss_clk_source_names[] = {
 static const struct dss_param_range omap2_dss_param_range[] = {
        [FEAT_PARAM_DSS_FCK]                    = { 0, 133000000 },
        [FEAT_PARAM_DSS_PCD]                    = { 2, 255 },
-       [FEAT_PARAM_DSIPLL_REGN]                = { 0, 0 },
-       [FEAT_PARAM_DSIPLL_REGM]                = { 0, 0 },
-       [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, 0 },
-       [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, 0 },
-       [FEAT_PARAM_DSIPLL_FINT]                = { 0, 0 },
-       [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, 0 },
        [FEAT_PARAM_DOWNSCALE]                  = { 1, 2 },
        /*
         * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
@@ -454,11 +432,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
 static const struct dss_param_range omap3_dss_param_range[] = {
        [FEAT_PARAM_DSS_FCK]                    = { 0, 173000000 },
        [FEAT_PARAM_DSS_PCD]                    = { 1, 255 },
-       [FEAT_PARAM_DSIPLL_REGN]                = { 0, (1 << 7) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM]                = { 0, (1 << 11) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, (1 << 4) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 4) - 1 },
-       [FEAT_PARAM_DSIPLL_FINT]                = { 750000, 2100000 },
        [FEAT_PARAM_DSIPLL_LPDIV]               = { 1, (1 << 13) - 1},
        [FEAT_PARAM_DSI_FCK]                    = { 0, 173000000 },
        [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
@@ -475,11 +448,6 @@ static const struct dss_param_range am43xx_dss_param_range[] = {
 static const struct dss_param_range omap4_dss_param_range[] = {
        [FEAT_PARAM_DSS_FCK]                    = { 0, 186000000 },
        [FEAT_PARAM_DSS_PCD]                    = { 1, 255 },
-       [FEAT_PARAM_DSIPLL_REGN]                = { 0, (1 << 8) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM]                = { 0, (1 << 12) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, (1 << 5) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 5) - 1 },
-       [FEAT_PARAM_DSIPLL_FINT]                = { 500000, 2500000 },
        [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, (1 << 13) - 1 },
        [FEAT_PARAM_DSI_FCK]                    = { 0, 170000000 },
        [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
@@ -489,11 +457,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
 static const struct dss_param_range omap5_dss_param_range[] = {
        [FEAT_PARAM_DSS_FCK]                    = { 0, 209250000 },
        [FEAT_PARAM_DSS_PCD]                    = { 1, 255 },
-       [FEAT_PARAM_DSIPLL_REGN]                = { 0, (1 << 8) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM]                = { 0, (1 << 12) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, (1 << 5) - 1 },
-       [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 5) - 1 },
-       [FEAT_PARAM_DSIPLL_FINT]                = { 150000, 52000000 },
        [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, (1 << 13) - 1 },
        [FEAT_PARAM_DSI_FCK]                    = { 0, 209250000 },
        [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
@@ -517,7 +480,6 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
        FEAT_LINEBUFFERSPLIT,
        FEAT_ROWREPEATENABLE,
        FEAT_RESIZECONF,
-       FEAT_DSI_PLL_FREQSEL,
        FEAT_DSI_REVERSE_TXCLKESC,
        FEAT_VENC_REQUIRES_TV_DAC_CLK,
        FEAT_CPR,
@@ -537,7 +499,6 @@ static const enum dss_feat_id am35xx_dss_feat_list[] = {
        FEAT_LINEBUFFERSPLIT,
        FEAT_ROWREPEATENABLE,
        FEAT_RESIZECONF,
-       FEAT_DSI_PLL_FREQSEL,
        FEAT_DSI_REVERSE_TXCLKESC,
        FEAT_VENC_REQUIRES_TV_DAC_CLK,
        FEAT_CPR,
@@ -572,7 +533,6 @@ static const enum dss_feat_id omap3630_dss_feat_list[] = {
        FEAT_ROWREPEATENABLE,
        FEAT_RESIZECONF,
        FEAT_DSI_PLL_PWR_BUG,
-       FEAT_DSI_PLL_FREQSEL,
        FEAT_CPR,
        FEAT_PRELOAD,
        FEAT_FIR_COEF_V,
@@ -654,8 +614,6 @@ static const enum dss_feat_id omap5_dss_feat_list[] = {
        FEAT_ALPHA_FREE_ZORDER,
        FEAT_FIFO_MERGE,
        FEAT_BURST_2D,
-       FEAT_DSI_PLL_SELFREQDCO,
-       FEAT_DSI_PLL_REFSEL,
        FEAT_DSI_PHY_DCC,
        FEAT_MFLAG,
 };
index e3ef3b714896086950f0ac2aceae86eaf6d0208b..100f7a2d0638475472053fd4e0d610c0bc90bfce 100644 (file)
@@ -41,7 +41,6 @@ enum dss_feat_id {
        FEAT_LCD_CLK_SRC,
        /* DSI-PLL power command 0x3 is not working */
        FEAT_DSI_PLL_PWR_BUG,
-       FEAT_DSI_PLL_FREQSEL,
        FEAT_DSI_DCS_CMD_CONFIG_VC,
        FEAT_DSI_VC_OCP_WIDTH,
        FEAT_DSI_REVERSE_TXCLKESC,
@@ -61,8 +60,6 @@ enum dss_feat_id {
        /* An unknown HW bug causing the normal FIFO thresholds not to work */
        FEAT_OMAP3_DSI_FIFO_BUG,
        FEAT_BURST_2D,
-       FEAT_DSI_PLL_SELFREQDCO,
-       FEAT_DSI_PLL_REFSEL,
        FEAT_DSI_PHY_DCC,
        FEAT_MFLAG,
 };
@@ -77,20 +74,11 @@ enum dss_feat_reg_field {
        FEAT_REG_HORIZONTALACCU,
        FEAT_REG_VERTICALACCU,
        FEAT_REG_DISPC_CLK_SWITCH,
-       FEAT_REG_DSIPLL_REGN,
-       FEAT_REG_DSIPLL_REGM,
-       FEAT_REG_DSIPLL_REGM_DISPC,
-       FEAT_REG_DSIPLL_REGM_DSI,
 };
 
 enum dss_range_param {
        FEAT_PARAM_DSS_FCK,
        FEAT_PARAM_DSS_PCD,
-       FEAT_PARAM_DSIPLL_REGN,
-       FEAT_PARAM_DSIPLL_REGM,
-       FEAT_PARAM_DSIPLL_REGM_DISPC,
-       FEAT_PARAM_DSIPLL_REGM_DSI,
-       FEAT_PARAM_DSIPLL_FINT,
        FEAT_PARAM_DSIPLL_LPDIV,
        FEAT_PARAM_DSI_FCK,
        FEAT_PARAM_DOWNSCALE,
index 262771b9b76b17c2cab7c5f204ddbd1b8d740410..e4a32fe77b0256fa0850e8ba59f5e5e2d9e96eef 100644 (file)
@@ -101,13 +101,6 @@ enum hdmi_core_hdmi_dvi {
        HDMI_HDMI = 1
 };
 
-enum hdmi_clk_refsel {
-       HDMI_REFSEL_PCLK = 0,
-       HDMI_REFSEL_REF1 = 1,
-       HDMI_REFSEL_REF2 = 2,
-       HDMI_REFSEL_SYSCLK = 3
-};
-
 enum hdmi_packing_mode {
        HDMI_PACK_10b_RGB_YUV444 = 0,
        HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
@@ -160,7 +153,8 @@ enum hdmi_audio_blk_strt_end_sig {
 
 enum hdmi_core_audio_layout {
        HDMI_AUDIO_LAYOUT_2CH = 0,
-       HDMI_AUDIO_LAYOUT_8CH = 1
+       HDMI_AUDIO_LAYOUT_8CH = 1,
+       HDMI_AUDIO_LAYOUT_6CH = 2
 };
 
 enum hdmi_core_cts_mode {
@@ -191,17 +185,6 @@ struct hdmi_config {
        enum hdmi_core_hdmi_dvi hdmi_dvi_mode;
 };
 
-/* HDMI PLL structure */
-struct hdmi_pll_info {
-       u16 regn;
-       u16 regm;
-       u32 regmf;
-       u16 regm2;
-       u16 regsd;
-       u16 dcofreq;
-       enum hdmi_clk_refsel refsel;
-};
-
 struct hdmi_audio_format {
        enum hdmi_stereo_channels               stereo_channels;
        u8                                      active_chnnls_msk;
@@ -249,12 +232,15 @@ struct hdmi_core_audio_config {
 
 struct hdmi_wp_data {
        void __iomem *base;
+       phys_addr_t phys_base;
 };
 
 struct hdmi_pll_data {
+       struct dss_pll pll;
+
        void __iomem *base;
 
-       struct hdmi_pll_info info;
+       struct hdmi_wp_data *wp;
 };
 
 struct hdmi_phy_data {
@@ -316,16 +302,19 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
 void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
                struct omap_video_timings *timings, struct hdmi_config *param);
 int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
+phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
 
 /* HDMI PLL funcs */
-int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
-void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
 void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
-void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy);
-int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll);
+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);
 
 /* HDMI PHY funcs */
-int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg);
+int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
+       unsigned long lfbitclk);
 void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
 int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
 int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
@@ -334,7 +323,7 @@ int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
 int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
        struct hdmi_phy_data *phy);
 
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
+/* Audio funcs */
 int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts);
 int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable);
 int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable);
@@ -342,9 +331,33 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
                struct hdmi_audio_format *aud_fmt);
 void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
                struct hdmi_audio_dma *aud_dma);
-static inline bool hdmi_mode_has_audio(int mode)
+static inline bool hdmi_mode_has_audio(struct hdmi_config *cfg)
 {
-       return mode == HDMI_HDMI ? true : false;
+       return cfg->hdmi_dvi_mode == HDMI_HDMI ? true : false;
 }
-#endif
+
+/* HDMI DRV data */
+struct omap_hdmi {
+       struct mutex lock;
+       struct platform_device *pdev;
+
+       struct hdmi_wp_data     wp;
+       struct hdmi_pll_data    pll;
+       struct hdmi_phy_data    phy;
+       struct hdmi_core_data   core;
+
+       struct hdmi_config cfg;
+
+       struct regulator *vdda_reg;
+
+       bool core_enabled;
+       bool display_enabled;
+
+       struct omap_dss_device output;
+
+       struct platform_device *audio_pdev;
+       void (*audio_abort_cb)(struct device *dev);
+       int wp_idlemode;
+};
+
 #endif
index 9a8713ca090c01561548a4e96d37cfd6fb5fb1db..f1a02bf938ee24011fefa86f7ee28409baedaac7 100644 (file)
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <video/omapdss.h>
+#include <sound/omap-hdmi-audio.h>
 
 #include "hdmi4_core.h"
 #include "dss.h"
 #include "dss_features.h"
+#include "hdmi.h"
 
-static struct {
-       struct mutex lock;
-       struct platform_device *pdev;
-
-       struct hdmi_wp_data     wp;
-       struct hdmi_pll_data    pll;
-       struct hdmi_phy_data    phy;
-       struct hdmi_core_data   core;
-
-       struct hdmi_config cfg;
-
-       struct clk *sys_clk;
-       struct regulator *vdda_hdmi_dac_reg;
-
-       bool core_enabled;
-
-       struct omap_dss_device output;
-} hdmi;
+static struct omap_hdmi hdmi;
 
 static int hdmi_runtime_get(void)
 {
@@ -117,7 +102,7 @@ static int hdmi_init_regulator(void)
        int r;
        struct regulator *reg;
 
-       if (hdmi.vdda_hdmi_dac_reg != NULL)
+       if (hdmi.vdda_reg != NULL)
                return 0;
 
        reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
@@ -137,7 +122,7 @@ static int hdmi_init_regulator(void)
                }
        }
 
-       hdmi.vdda_hdmi_dac_reg = reg;
+       hdmi.vdda_reg = reg;
 
        return 0;
 }
@@ -146,7 +131,7 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
 {
        int r;
 
-       r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
+       r = regulator_enable(hdmi.vdda_reg);
        if (r)
                return r;
 
@@ -162,7 +147,7 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
        return 0;
 
 err_runtime_get:
-       regulator_disable(hdmi.vdda_hdmi_dac_reg);
+       regulator_disable(hdmi.vdda_reg);
 
        return r;
 }
@@ -172,7 +157,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev)
        hdmi.core_enabled = false;
 
        hdmi_runtime_put();
-       regulator_disable(hdmi.vdda_hdmi_dac_reg);
+       regulator_disable(hdmi.vdda_reg);
 }
 
 static int hdmi_power_on_full(struct omap_dss_device *dssdev)
@@ -180,8 +165,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
        int r;
        struct omap_video_timings *p;
        struct omap_overlay_manager *mgr = hdmi.output.manager;
-       unsigned long phy;
        struct hdmi_wp_data *wp = &hdmi.wp;
+       struct dss_pll_clock_info hdmi_cinfo = { 0 };
 
        r = hdmi_power_on_core(dssdev);
        if (r)
@@ -195,19 +180,22 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
 
        DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
 
-       /* the functions below use kHz pixel clock. TODO: change to Hz */
-       phy = p->pixelclock / 1000;
-
-       hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
+       hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo);
 
-       /* config the PLL and PHY hdmi_set_pll_pwrfirst */
-       r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
+       r = dss_pll_enable(&hdmi.pll.pll);
        if (r) {
-               DSSDBG("Failed to lock PLL\n");
+               DSSERR("Failed to enable PLL\n");
                goto err_pll_enable;
        }
 
-       r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg);
+       r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo);
+       if (r) {
+               DSSERR("Failed to configure PLL\n");
+               goto err_pll_cfg;
+       }
+
+       r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco,
+               hdmi_cinfo.clkout[0]);
        if (r) {
                DSSDBG("Failed to configure PHY\n");
                goto err_phy_cfg;
@@ -244,7 +232,8 @@ err_vid_enable:
 err_phy_cfg:
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 err_phy_pwr:
-       hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
+err_pll_cfg:
+       dss_pll_disable(&hdmi.pll.pll);
 err_pll_enable:
        hdmi_power_off_core(dssdev);
        return -EIO;
@@ -262,7 +251,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 
-       hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
+       dss_pll_disable(&hdmi.pll.pll);
 
        hdmi_power_off_core(dssdev);
 }
@@ -352,6 +341,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
+       hdmi.display_enabled = true;
+
        mutex_unlock(&hdmi.lock);
        return 0;
 
@@ -366,8 +357,13 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
 
        mutex_lock(&hdmi.lock);
 
+       if (hdmi.audio_pdev && hdmi.audio_abort_cb)
+               hdmi.audio_abort_cb(&hdmi.audio_pdev->dev);
+
        hdmi_power_off_full(dssdev);
 
+       hdmi.display_enabled = false;
+
        mutex_unlock(&hdmi.lock);
 }
 
@@ -404,21 +400,6 @@ static void hdmi_core_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&hdmi.lock);
 }
 
-static int hdmi_get_clocks(struct platform_device *pdev)
-{
-       struct clk *clk;
-
-       clk = devm_clk_get(&pdev->dev, "sys_clk");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get sys_clk\n");
-               return PTR_ERR(clk);
-       }
-
-       hdmi.sys_clk = clk;
-
-       return 0;
-}
-
 static int hdmi_connect(struct omap_dss_device *dssdev,
                struct omap_dss_device *dst)
 {
@@ -484,112 +465,6 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev,
        return r;
 }
 
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-static int hdmi_audio_enable(struct omap_dss_device *dssdev)
-{
-       int r;
-
-       mutex_lock(&hdmi.lock);
-
-       if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
-               r = -EPERM;
-               goto err;
-       }
-
-       r = hdmi_wp_audio_enable(&hdmi.wp, true);
-       if (r)
-               goto err;
-
-       mutex_unlock(&hdmi.lock);
-       return 0;
-
-err:
-       mutex_unlock(&hdmi.lock);
-       return r;
-}
-
-static void hdmi_audio_disable(struct omap_dss_device *dssdev)
-{
-       hdmi_wp_audio_enable(&hdmi.wp, false);
-}
-
-static int hdmi_audio_start(struct omap_dss_device *dssdev)
-{
-       return hdmi4_audio_start(&hdmi.core, &hdmi.wp);
-}
-
-static void hdmi_audio_stop(struct omap_dss_device *dssdev)
-{
-       hdmi4_audio_stop(&hdmi.core, &hdmi.wp);
-}
-
-static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
-{
-       bool r;
-
-       mutex_lock(&hdmi.lock);
-
-       r = hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode);
-
-       mutex_unlock(&hdmi.lock);
-       return r;
-}
-
-static int hdmi_audio_config(struct omap_dss_device *dssdev,
-               struct omap_dss_audio *audio)
-{
-       int r;
-       u32 pclk = hdmi.cfg.timings.pixelclock;
-
-       mutex_lock(&hdmi.lock);
-
-       if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
-               r = -EPERM;
-               goto err;
-       }
-
-       r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
-       if (r)
-               goto err;
-
-       mutex_unlock(&hdmi.lock);
-       return 0;
-
-err:
-       mutex_unlock(&hdmi.lock);
-       return r;
-}
-#else
-static int hdmi_audio_enable(struct omap_dss_device *dssdev)
-{
-       return -EPERM;
-}
-
-static void hdmi_audio_disable(struct omap_dss_device *dssdev)
-{
-}
-
-static int hdmi_audio_start(struct omap_dss_device *dssdev)
-{
-       return -EPERM;
-}
-
-static void hdmi_audio_stop(struct omap_dss_device *dssdev)
-{
-}
-
-static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
-{
-       return false;
-}
-
-static int hdmi_audio_config(struct omap_dss_device *dssdev,
-               struct omap_dss_audio *audio)
-{
-       return -EPERM;
-}
-#endif
-
 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
                const struct hdmi_avi_infoframe *avi)
 {
@@ -618,13 +493,6 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
        .read_edid              = hdmi_read_edid,
        .set_infoframe          = hdmi_set_infoframe,
        .set_hdmi_mode          = hdmi_set_hdmi_mode,
-
-       .audio_enable           = hdmi_audio_enable,
-       .audio_disable          = hdmi_audio_disable,
-       .audio_start            = hdmi_audio_start,
-       .audio_stop             = hdmi_audio_stop,
-       .audio_supported        = hdmi_audio_supported,
-       .audio_config           = hdmi_audio_config,
 };
 
 static void hdmi_init_output(struct platform_device *pdev)
@@ -642,7 +510,7 @@ static void hdmi_init_output(struct platform_device *pdev)
        omapdss_register_output(out);
 }
 
-static void __exit hdmi_uninit_output(struct platform_device *pdev)
+static void hdmi_uninit_output(struct platform_device *pdev)
 {
        struct omap_dss_device *out = &hdmi.output;
 
@@ -671,6 +539,112 @@ err:
        return r;
 }
 
+/* Audio callbacks */
+static int hdmi_audio_startup(struct device *dev,
+                             void (*abort_cb)(struct device *dev))
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+       int ret = 0;
+
+       mutex_lock(&hd->lock);
+
+       if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       hd->audio_abort_cb = abort_cb;
+
+out:
+       mutex_unlock(&hd->lock);
+
+       return ret;
+}
+
+static int hdmi_audio_shutdown(struct device *dev)
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+
+       mutex_lock(&hd->lock);
+       hd->audio_abort_cb = NULL;
+       mutex_unlock(&hd->lock);
+
+       return 0;
+}
+
+static int hdmi_audio_start(struct device *dev)
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+
+       WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
+       WARN_ON(!hd->display_enabled);
+
+       hdmi_wp_audio_enable(&hd->wp, true);
+       hdmi4_audio_start(&hd->core, &hd->wp);
+
+       return 0;
+}
+
+static void hdmi_audio_stop(struct device *dev)
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+
+       WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
+       WARN_ON(!hd->display_enabled);
+
+       hdmi4_audio_stop(&hd->core, &hd->wp);
+       hdmi_wp_audio_enable(&hd->wp, false);
+}
+
+static int hdmi_audio_config(struct device *dev,
+                            struct omap_dss_audio *dss_audio)
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+       int ret;
+
+       mutex_lock(&hd->lock);
+
+       if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio,
+                                hd->cfg.timings.pixelclock);
+
+out:
+       mutex_unlock(&hd->lock);
+
+       return ret;
+}
+
+static const struct omap_hdmi_audio_ops hdmi_audio_ops = {
+       .audio_startup = hdmi_audio_startup,
+       .audio_shutdown = hdmi_audio_shutdown,
+       .audio_start = hdmi_audio_start,
+       .audio_stop = hdmi_audio_stop,
+       .audio_config = hdmi_audio_config,
+};
+
+static int hdmi_audio_register(struct device *dev)
+{
+       struct omap_hdmi_audio_pdata pdata = {
+               .dev = dev,
+               .dss_version = omapdss_get_version(),
+               .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
+               .ops = &hdmi_audio_ops,
+       };
+
+       hdmi.audio_pdev = platform_device_register_data(
+               dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO,
+               &pdata, sizeof(pdata));
+
+       if (IS_ERR(hdmi.audio_pdev))
+               return PTR_ERR(hdmi.audio_pdev);
+
+       return 0;
+}
+
 /* HDMI HW IP initialisation */
 static int omapdss_hdmihw_probe(struct platform_device *pdev)
 {
@@ -678,6 +652,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
        int irq;
 
        hdmi.pdev = pdev;
+       dev_set_drvdata(&pdev->dev, &hdmi);
 
        mutex_init(&hdmi.lock);
 
@@ -691,28 +666,23 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
        if (r)
                return r;
 
-       r = hdmi_pll_init(pdev, &hdmi.pll);
+       r = hdmi_pll_init(pdev, &hdmi.pll, &hdmi.wp);
        if (r)
                return r;
 
        r = hdmi_phy_init(pdev, &hdmi.phy);
        if (r)
-               return r;
+               goto err;
 
        r = hdmi4_core_init(pdev, &hdmi.core);
        if (r)
-               return r;
-
-       r = hdmi_get_clocks(pdev);
-       if (r) {
-               DSSERR("can't get clocks\n");
-               return r;
-       }
+               goto err;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                DSSERR("platform_get_irq failed\n");
-               return -ENODEV;
+               r = -ENODEV;
+               goto err;
        }
 
        r = devm_request_threaded_irq(&pdev->dev, irq,
@@ -720,22 +690,38 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
                        IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
        if (r) {
                DSSERR("HDMI IRQ request failed\n");
-               return r;
+               goto err;
        }
 
        pm_runtime_enable(&pdev->dev);
 
        hdmi_init_output(pdev);
 
+       r = hdmi_audio_register(&pdev->dev);
+       if (r) {
+               DSSERR("Registering HDMI audio failed\n");
+               hdmi_uninit_output(pdev);
+               pm_runtime_disable(&pdev->dev);
+               return r;
+       }
+
        dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
        return 0;
+err:
+       hdmi_pll_uninit(&hdmi.pll);
+       return r;
 }
 
 static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 {
+       if (hdmi.audio_pdev)
+               platform_device_unregister(hdmi.audio_pdev);
+
        hdmi_uninit_output(pdev);
 
+       hdmi_pll_uninit(&hdmi.pll);
+
        pm_runtime_disable(&pdev->dev);
 
        return 0;
@@ -743,8 +729,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 
 static int hdmi_runtime_suspend(struct device *dev)
 {
-       clk_disable_unprepare(hdmi.sys_clk);
-
        dispc_runtime_put();
 
        return 0;
@@ -758,8 +742,6 @@ static int hdmi_runtime_resume(struct device *dev)
        if (r < 0)
                return r;
 
-       clk_prepare_enable(hdmi.sys_clk);
-
        return 0;
 }
 
index 4ad39cfce254aa41ec41c09a4cf961555eecfdf0..7eafea5b8e190c15f03a51e12ca28ad830acc647 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 #include <sound/asound.h>
 #include <sound/asoundef.h>
-#endif
 
 #include "hdmi4_core.h"
 #include "dss_features.h"
@@ -530,7 +528,6 @@ void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s)
        DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID);
 }
 
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 static void hdmi_core_audio_config(struct hdmi_core_data *core,
                                        struct hdmi_core_audio_config *cfg)
 {
@@ -877,17 +874,6 @@ void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
        hdmi_wp_audio_core_req_enable(wp, false);
 }
 
-int hdmi4_audio_get_dma_port(u32 *offset, u32 *size)
-{
-       if (!offset || !size)
-               return -EINVAL;
-       *offset = HDMI_WP_AUDIO_DATA;
-       *size = 4;
-       return 0;
-}
-
-#endif
-
 int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
 {
        struct resource *res;
index 827909eb6c503a44ab4dff29ac4a7dd1db56fa84..a069f96ec6f66b08f8a2c8e95e9151650a80e04f 100644 (file)
@@ -266,12 +266,8 @@ void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
 void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s);
 int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
 
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
 void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
 int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
                struct omap_dss_audio *audio, u32 pclk);
-int hdmi4_audio_get_dma_port(u32 *offset, u32 *size);
-#endif
-
 #endif
index 169b764bb9d48f6cb188d075a740e0cd4da4dbb3..d9d0d781625af34c20118909ec48cb37f18865d3 100644 (file)
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <video/omapdss.h>
+#include <sound/omap-hdmi-audio.h>
 
 #include "hdmi5_core.h"
 #include "dss.h"
 #include "dss_features.h"
 
-static struct {
-       struct mutex lock;
-       struct platform_device *pdev;
-
-       struct hdmi_wp_data     wp;
-       struct hdmi_pll_data    pll;
-       struct hdmi_phy_data    phy;
-       struct hdmi_core_data   core;
-
-       struct hdmi_config cfg;
-
-       struct clk *sys_clk;
-       struct regulator *vdda_reg;
-
-       bool core_enabled;
-
-       struct omap_dss_device output;
-} hdmi;
+static struct omap_hdmi hdmi;
 
 static int hdmi_runtime_get(void)
 {
@@ -198,7 +182,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
        int r;
        struct omap_video_timings *p;
        struct omap_overlay_manager *mgr = hdmi.output.manager;
-       unsigned long phy;
+       struct dss_pll_clock_info hdmi_cinfo = { 0 };
 
        r = hdmi_power_on_core(dssdev);
        if (r)
@@ -208,24 +192,27 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
 
        DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
 
-       /* the functions below use kHz pixel clock. TODO: change to Hz */
-       phy = p->pixelclock / 1000;
-
-       hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
+       hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo);
 
        /* disable and clear irqs */
        hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
        hdmi_wp_set_irqstatus(&hdmi.wp,
                        hdmi_wp_get_irqstatus(&hdmi.wp));
 
-       /* config the PLL and PHY hdmi_set_pll_pwrfirst */
-       r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
+       r = dss_pll_enable(&hdmi.pll.pll);
        if (r) {
-               DSSDBG("Failed to lock PLL\n");
+               DSSERR("Failed to enable PLL\n");
                goto err_pll_enable;
        }
 
-       r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg);
+       r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo);
+       if (r) {
+               DSSERR("Failed to configure PLL\n");
+               goto err_pll_cfg;
+       }
+
+       r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco,
+               hdmi_cinfo.clkout[0]);
        if (r) {
                DSSDBG("Failed to start PHY\n");
                goto err_phy_cfg;
@@ -262,7 +249,8 @@ err_vid_enable:
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 err_phy_pwr:
 err_phy_cfg:
-       hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
+err_pll_cfg:
+       dss_pll_disable(&hdmi.pll.pll);
 err_pll_enable:
        hdmi_power_off_core(dssdev);
        return -EIO;
@@ -280,7 +268,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 
-       hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
+       dss_pll_disable(&hdmi.pll.pll);
 
        hdmi_power_off_core(dssdev);
 }
@@ -290,6 +278,10 @@ static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
 {
        struct omap_dss_device *out = &hdmi.output;
 
+       /* TODO: proper interlace support */
+       if (timings->interlace)
+               return -EINVAL;
+
        if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
                return -EINVAL;
 
@@ -377,6 +369,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
+       hdmi.display_enabled = true;
+
        mutex_unlock(&hdmi.lock);
        return 0;
 
@@ -391,8 +385,13 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
 
        mutex_lock(&hdmi.lock);
 
+       if (hdmi.audio_pdev && hdmi.audio_abort_cb)
+               hdmi.audio_abort_cb(&hdmi.audio_pdev->dev);
+
        hdmi_power_off_full(dssdev);
 
+       hdmi.display_enabled = false;
+
        mutex_unlock(&hdmi.lock);
 }
 
@@ -429,21 +428,6 @@ static void hdmi_core_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&hdmi.lock);
 }
 
-static int hdmi_get_clocks(struct platform_device *pdev)
-{
-       struct clk *clk;
-
-       clk = devm_clk_get(&pdev->dev, "sys_clk");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get sys_clk\n");
-               return PTR_ERR(clk);
-       }
-
-       hdmi.sys_clk = clk;
-
-       return 0;
-}
-
 static int hdmi_connect(struct omap_dss_device *dssdev,
                struct omap_dss_device *dst)
 {
@@ -509,112 +493,6 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev,
        return r;
 }
 
-#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
-static int hdmi_audio_enable(struct omap_dss_device *dssdev)
-{
-       int r;
-
-       mutex_lock(&hdmi.lock);
-
-       if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
-               r = -EPERM;
-               goto err;
-       }
-
-       r = hdmi_wp_audio_enable(&hdmi.wp, true);
-       if (r)
-               goto err;
-
-       mutex_unlock(&hdmi.lock);
-       return 0;
-
-err:
-       mutex_unlock(&hdmi.lock);
-       return r;
-}
-
-static void hdmi_audio_disable(struct omap_dss_device *dssdev)
-{
-       hdmi_wp_audio_enable(&hdmi.wp, false);
-}
-
-static int hdmi_audio_start(struct omap_dss_device *dssdev)
-{
-       return hdmi_wp_audio_core_req_enable(&hdmi.wp, true);
-}
-
-static void hdmi_audio_stop(struct omap_dss_device *dssdev)
-{
-       hdmi_wp_audio_core_req_enable(&hdmi.wp, false);
-}
-
-static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
-{
-       bool r;
-
-       mutex_lock(&hdmi.lock);
-
-       r = hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode);
-
-       mutex_unlock(&hdmi.lock);
-       return r;
-}
-
-static int hdmi_audio_config(struct omap_dss_device *dssdev,
-               struct omap_dss_audio *audio)
-{
-       int r;
-       u32 pclk = hdmi.cfg.timings.pixelclock;
-
-       mutex_lock(&hdmi.lock);
-
-       if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
-               r = -EPERM;
-               goto err;
-       }
-
-       r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
-       if (r)
-               goto err;
-
-       mutex_unlock(&hdmi.lock);
-       return 0;
-
-err:
-       mutex_unlock(&hdmi.lock);
-       return r;
-}
-#else
-static int hdmi_audio_enable(struct omap_dss_device *dssdev)
-{
-       return -EPERM;
-}
-
-static void hdmi_audio_disable(struct omap_dss_device *dssdev)
-{
-}
-
-static int hdmi_audio_start(struct omap_dss_device *dssdev)
-{
-       return -EPERM;
-}
-
-static void hdmi_audio_stop(struct omap_dss_device *dssdev)
-{
-}
-
-static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
-{
-       return false;
-}
-
-static int hdmi_audio_config(struct omap_dss_device *dssdev,
-               struct omap_dss_audio *audio)
-{
-       return -EPERM;
-}
-#endif
-
 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
                const struct hdmi_avi_infoframe *avi)
 {
@@ -643,13 +521,6 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
        .read_edid              = hdmi_read_edid,
        .set_infoframe          = hdmi_set_infoframe,
        .set_hdmi_mode          = hdmi_set_hdmi_mode,
-
-       .audio_enable           = hdmi_audio_enable,
-       .audio_disable          = hdmi_audio_disable,
-       .audio_start            = hdmi_audio_start,
-       .audio_stop             = hdmi_audio_stop,
-       .audio_supported        = hdmi_audio_supported,
-       .audio_config           = hdmi_audio_config,
 };
 
 static void hdmi_init_output(struct platform_device *pdev)
@@ -667,7 +538,7 @@ static void hdmi_init_output(struct platform_device *pdev)
        omapdss_register_output(out);
 }
 
-static void __exit hdmi_uninit_output(struct platform_device *pdev)
+static void hdmi_uninit_output(struct platform_device *pdev)
 {
        struct omap_dss_device *out = &hdmi.output;
 
@@ -696,6 +567,119 @@ err:
        return r;
 }
 
+/* Audio callbacks */
+static int hdmi_audio_startup(struct device *dev,
+                             void (*abort_cb)(struct device *dev))
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+       int ret = 0;
+
+       mutex_lock(&hd->lock);
+
+       if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       hd->audio_abort_cb = abort_cb;
+
+out:
+       mutex_unlock(&hd->lock);
+
+       return ret;
+}
+
+static int hdmi_audio_shutdown(struct device *dev)
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+
+       mutex_lock(&hd->lock);
+       hd->audio_abort_cb = NULL;
+       mutex_unlock(&hd->lock);
+
+       return 0;
+}
+
+static int hdmi_audio_start(struct device *dev)
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+
+       WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
+       WARN_ON(!hd->display_enabled);
+
+       /* No-idle while playing audio, store the old value */
+       hd->wp_idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
+       REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+
+       hdmi_wp_audio_enable(&hd->wp, true);
+       hdmi_wp_audio_core_req_enable(&hd->wp, true);
+
+       return 0;
+}
+
+static void hdmi_audio_stop(struct device *dev)
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+
+       WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
+       WARN_ON(!hd->display_enabled);
+
+       hdmi_wp_audio_core_req_enable(&hd->wp, false);
+       hdmi_wp_audio_enable(&hd->wp, false);
+
+       /* Playback stopped, restore original idlemode */
+       REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
+}
+
+static int hdmi_audio_config(struct device *dev,
+                            struct omap_dss_audio *dss_audio)
+{
+       struct omap_hdmi *hd = dev_get_drvdata(dev);
+       int ret;
+
+       mutex_lock(&hd->lock);
+
+       if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio,
+                                hd->cfg.timings.pixelclock);
+
+out:
+       mutex_unlock(&hd->lock);
+
+       return ret;
+}
+
+static const struct omap_hdmi_audio_ops hdmi_audio_ops = {
+       .audio_startup = hdmi_audio_startup,
+       .audio_shutdown = hdmi_audio_shutdown,
+       .audio_start = hdmi_audio_start,
+       .audio_stop = hdmi_audio_stop,
+       .audio_config = hdmi_audio_config,
+};
+
+static int hdmi_audio_register(struct device *dev)
+{
+       struct omap_hdmi_audio_pdata pdata = {
+               .dev = dev,
+               .dss_version = omapdss_get_version(),
+               .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
+               .ops = &hdmi_audio_ops,
+       };
+
+       hdmi.audio_pdev = platform_device_register_data(
+               dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO,
+               &pdata, sizeof(pdata));
+
+       if (IS_ERR(hdmi.audio_pdev))
+               return PTR_ERR(hdmi.audio_pdev);
+
+       return 0;
+}
+
 /* HDMI HW IP initialisation */
 static int omapdss_hdmihw_probe(struct platform_device *pdev)
 {
@@ -703,6 +687,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
        int irq;
 
        hdmi.pdev = pdev;
+       dev_set_drvdata(&pdev->dev, &hdmi);
 
        mutex_init(&hdmi.lock);
 
@@ -716,28 +701,23 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
        if (r)
                return r;
 
-       r = hdmi_pll_init(pdev, &hdmi.pll);
+       r = hdmi_pll_init(pdev, &hdmi.pll, &hdmi.wp);
        if (r)
                return r;
 
        r = hdmi_phy_init(pdev, &hdmi.phy);
        if (r)
-               return r;
+               goto err;
 
        r = hdmi5_core_init(pdev, &hdmi.core);
        if (r)
-               return r;
-
-       r = hdmi_get_clocks(pdev);
-       if (r) {
-               DSSERR("can't get clocks\n");
-               return r;
-       }
+               goto err;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                DSSERR("platform_get_irq failed\n");
-               return -ENODEV;
+               r = -ENODEV;
+               goto err;
        }
 
        r = devm_request_threaded_irq(&pdev->dev, irq,
@@ -745,22 +725,38 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
                        IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
        if (r) {
                DSSERR("HDMI IRQ request failed\n");
-               return r;
+               goto err;
        }
 
        pm_runtime_enable(&pdev->dev);
 
        hdmi_init_output(pdev);
 
+       r = hdmi_audio_register(&pdev->dev);
+       if (r) {
+               DSSERR("Registering HDMI audio failed %d\n", r);
+               hdmi_uninit_output(pdev);
+               pm_runtime_disable(&pdev->dev);
+               return r;
+       }
+
        dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
        return 0;
+err:
+       hdmi_pll_uninit(&hdmi.pll);
+       return r;
 }
 
 static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 {
+       if (hdmi.audio_pdev)
+               platform_device_unregister(hdmi.audio_pdev);
+
        hdmi_uninit_output(pdev);
 
+       hdmi_pll_uninit(&hdmi.pll);
+
        pm_runtime_disable(&pdev->dev);
 
        return 0;
@@ -768,8 +764,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 
 static int hdmi_runtime_suspend(struct device *dev)
 {
-       clk_disable_unprepare(hdmi.sys_clk);
-
        dispc_runtime_put();
 
        return 0;
@@ -783,8 +777,6 @@ static int hdmi_runtime_resume(struct device *dev)
        if (r < 0)
                return r;
 
-       clk_prepare_enable(hdmi.sys_clk);
-
        return 0;
 }
 
index 83acbf7a8c89c9ddb4df68f9a7fe0d926a0c55d0..a3cfe3d708f7a5b47389f41791000615485539c7 100644 (file)
 #include <linux/string.h>
 #include <linux/seq_file.h>
 #include <drm/drm_edid.h>
-#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
 #include <sound/asound.h>
 #include <sound/asoundef.h>
-#endif
 
 #include "hdmi5_core.h"
 
@@ -644,9 +642,6 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
        hdmi_core_enable_interrupts(core);
 }
 
-
-#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
-
 static void hdmi5_core_audio_config(struct hdmi_core_data *core,
                        struct hdmi_core_audio_config *cfg)
 {
@@ -721,7 +716,7 @@ static void hdmi5_core_audio_config(struct hdmi_core_data *core,
 
        /* Source number */
        val = cfg->iec60958_cfg->status[2] & IEC958_AES2_CON_SOURCE;
-       REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(2), val, 3, 4);
+       REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(2), val, 3, 0);
 
        /* Channel number right 0  */
        REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(3), 2, 3, 0);
@@ -879,6 +874,9 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
        /* only LPCM atm */
        audio_format.type = HDMI_AUDIO_TYPE_LPCM;
 
+       /* only allowed option */
+       audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
+
        /* disable start/stop signals of IEC 60958 blocks */
        audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
 
@@ -894,7 +892,6 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
 
        return 0;
 }
-#endif
 
 int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
 {
index ce7e9f376f045cd0258a7f0337fa6ebdf73bf474..f2f1022c55166e12caec536af31261a02bd36c9c 100644 (file)
@@ -299,8 +299,6 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
                        struct hdmi_config *cfg);
 int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
 
-#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
 int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
                        struct omap_dss_audio *audio, u32 pclk);
 #endif
-#endif
index 7d5f1039de9f3fffe00f3d8f2ecf8d5acc4b11b5..1b8fcc6c4ba1ba9381709d4970cb25a950640fdb 100644 (file)
@@ -48,7 +48,6 @@ int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
        return 0;
 }
 
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
 {
        u32 deep_color;
@@ -147,4 +146,3 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
 
        return 0;
 }
-#endif
index e007ac892d79aec1f790688bf7fda9b38875194a..bc9e07d2afbe5132b56634b7a6b4a4c68ae74c84 100644 (file)
@@ -20,9 +20,7 @@
 
 struct hdmi_phy_features {
        bool bist_ctrl;
-       bool calc_freqout;
        bool ldo_voltage;
-       unsigned long dcofreq_min;
        unsigned long max_phy;
 };
 
@@ -132,7 +130,8 @@ static void hdmi_phy_configure_lanes(struct hdmi_phy_data *phy)
        REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27);
 }
 
-int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
+int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
+       unsigned long lfbitclk)
 {
        u8 freqout;
 
@@ -149,20 +148,16 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
        if (phy_feat->bist_ctrl)
                REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11);
 
-       if (phy_feat->calc_freqout) {
-               /* DCOCLK/10 is pixel clock, compare pclk with DCOCLK_MIN/10 */
-               u32 dco_min = phy_feat->dcofreq_min / 10;
-               u32 pclk = cfg->timings.pixelclock;
-
-               if (pclk < dco_min)
-                       freqout = 0;
-               else if ((pclk >= dco_min) && (pclk < phy_feat->max_phy))
-                       freqout = 1;
-               else
-                       freqout = 2;
-       } else {
+       /*
+        * If the hfbitclk != lfbitclk, it means the lfbitclk was configured
+        * to be used for TMDS.
+        */
+       if (hfbitclk != lfbitclk)
+               freqout = 0;
+       else if (hfbitclk / 10 < phy_feat->max_phy)
                freqout = 1;
-       }
+       else
+               freqout = 2;
 
        /*
         * Write to phy address 0 to configure the clock
@@ -184,17 +179,13 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
 
 static const struct hdmi_phy_features omap44xx_phy_feats = {
        .bist_ctrl      =       false,
-       .calc_freqout   =       false,
        .ldo_voltage    =       true,
-       .dcofreq_min    =       500000000,
        .max_phy        =       185675000,
 };
 
 static const struct hdmi_phy_features omap54xx_phy_feats = {
        .bist_ctrl      =       true,
-       .calc_freqout   =       true,
        .ldo_voltage    =       false,
-       .dcofreq_min    =       750000000,
        .max_phy        =       186000000,
 };
 
index 6d92bb32fe5192e90333b8a38b0db4fa95f341e9..87accdb59c81b5ed5686ad2c291c636fe541289a 100644 (file)
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
+
 #include <video/omapdss.h>
 
 #include "dss.h"
 #include "hdmi.h"
 
-#define HDMI_DEFAULT_REGN 16
-#define HDMI_DEFAULT_REGM2 1
-
-struct hdmi_pll_features {
-       bool sys_reset;
-       /* this is a hack, need to replace it with a better computation of M2 */
-       bool bound_dcofreq;
-       unsigned long fint_min, fint_max;
-       u16 regm_max;
-       unsigned long dcofreq_low_min, dcofreq_low_max;
-       unsigned long dcofreq_high_min, dcofreq_high_max;
-};
-
-static const struct hdmi_pll_features *pll_feat;
-
 void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
 {
 #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
@@ -51,228 +38,189 @@ 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 clkin, int phy)
+void hdmi_pll_compute(struct hdmi_pll_data *pll,
+       unsigned long target_tmds, struct dss_pll_clock_info *pi)
 {
-       struct hdmi_pll_info *pi = &pll->info;
-       unsigned long refclk;
-       u32 mf;
+       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;
 
-       /* use our funky units */
-       clkin /= 10000;
+       clkin = clk_get_rate(pll->pll.clkin);
 
-       /*
-        * Input clock is predivided by N + 1
-        * out put of which is reference clk
-        */
+       DSSDBG("clkin %lu, target tmds %lu\n", clkin, target_tmds);
 
-       pi->regn = HDMI_DEFAULT_REGN;
+       target_bitclk = target_tmds * 10;
 
-       refclk = clkin / pi->regn;
+       /* Fint */
+       n = DIV_ROUND_UP(clkin, hw->fint_max);
+       fint = clkin / n;
 
-       /* temorary hack to make sure DCO freq isn't calculated too low */
-       if (pll_feat->bound_dcofreq && phy <= 65000)
-               pi->regm2 = 3;
-       else
-               pi->regm2 = HDMI_DEFAULT_REGM2;
-
-       /*
-        * multiplier is pixel_clk/ref_clk
-        * Multiplying by 100 to avoid fractional part removal
-        */
-       pi->regm = phy * pi->regm2 / refclk;
-
-       /*
-        * fractional multiplier is remainder of the difference between
-        * multiplier and actual phy(required pixel clock thus should be
-        * multiplied by 2^18(262144) divided by the reference clock
-        */
-       mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
-       pi->regmf = pi->regm2 * mf / refclk;
-
-       /*
-        * Dcofreq should be set to 1 if required pixel clock
-        * is greater than 1000MHz
-        */
-       pi->dcofreq = phy > 1000 * 100;
-       pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
-
-       /* Set the reference clock to sysclk reference */
-       pi->refsel = HDMI_REFSEL_SYSCLK;
-
-       DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
-       DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
-}
+       /* 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;
 
-static int hdmi_pll_config(struct hdmi_pll_data *pll)
-{
-       u32 r;
-       struct hdmi_pll_info *fmt = &pll->info;
+       clkdco = fint * m;
 
-       /* PLL start always use manual mode */
-       REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
-
-       r = hdmi_read_reg(pll->base, PLLCTRL_CFG1);
-       r = FLD_MOD(r, fmt->regm, 20, 9);       /* CFG1_PLL_REGM */
-       r = FLD_MOD(r, fmt->regn - 1, 8, 1);    /* CFG1_PLL_REGN */
-       hdmi_write_reg(pll->base, PLLCTRL_CFG1, r);
-
-       r = hdmi_read_reg(pll->base, PLLCTRL_CFG2);
-
-       r = FLD_MOD(r, 0x0, 12, 12);    /* PLL_HIGHFREQ divide by 2 */
-       r = FLD_MOD(r, 0x1, 13, 13);    /* PLL_REFEN */
-       r = FLD_MOD(r, 0x0, 14, 14);    /* PHY_CLKINEN de-assert during locking */
-       r = FLD_MOD(r, fmt->refsel, 22, 21);    /* REFSEL */
-
-       if (fmt->dcofreq)
-               r = FLD_MOD(r, 0x4, 3, 1);      /* 1000MHz and 2000MHz */
+       /* adjust clkdco with fractional mf */
+       if (WARN_ON(target_clkdco - clkdco > fint))
+               mf = 0;
        else
-               r = FLD_MOD(r, 0x2, 3, 1);      /* 500MHz and 1000MHz */
-
-       hdmi_write_reg(pll->base, PLLCTRL_CFG2, r);
-
-       REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
+               mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
 
-       r = hdmi_read_reg(pll->base, PLLCTRL_CFG4);
-       r = FLD_MOD(r, fmt->regm2, 24, 18);
-       r = FLD_MOD(r, fmt->regmf, 17, 0);
-       hdmi_write_reg(pll->base, PLLCTRL_CFG4, r);
+       if (mf > 0)
+               clkdco += (u32)div_u64((u64)mf * fint, 262144);
 
-       /* go now */
-       REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0);
+       clkout = clkdco / m2;
 
-       /* wait for bit change */
-       if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO,
-                       0, 0, 0) != 0) {
-               DSSERR("PLL GO bit not clearing\n");
-               return -ETIMEDOUT;
-       }
+       /* sigma-delta */
+       sd = DIV_ROUND_UP(fint * m, 250000000);
 
-       /* Wait till the lock bit is set in PLL status */
-       if (hdmi_wait_for_bit_change(pll->base,
-                       PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
-               DSSERR("cannot lock PLL\n");
-               DSSERR("CFG1 0x%x\n",
-                       hdmi_read_reg(pll->base, PLLCTRL_CFG1));
-               DSSERR("CFG2 0x%x\n",
-                       hdmi_read_reg(pll->base, PLLCTRL_CFG2));
-               DSSERR("CFG4 0x%x\n",
-                       hdmi_read_reg(pll->base, PLLCTRL_CFG4));
-               return -ETIMEDOUT;
-       }
+       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);
 
-       DSSDBG("PLL locked!\n");
+       pi->n = n;
+       pi->m = m;
+       pi->mf = mf;
+       pi->mX[0] = m2;
+       pi->sd = sd;
 
-       return 0;
+       pi->fint = fint;
+       pi->clkdco = clkdco;
+       pi->clkout[0] = clkout;
 }
 
-static int hdmi_pll_reset(struct hdmi_pll_data *pll)
-{
-       /* SYSRESET  controlled by power FSM */
-       REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, pll_feat->sys_reset, 3, 3);
-
-       /* READ 0x0 reset is in progress */
-       if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1)
-                       != 1) {
-               DSSERR("Failed to sysreset PLL\n");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
+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;
 
-       r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
-       if (r)
-               return r;
-
        r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
        if (r)
                return r;
 
-       r = hdmi_pll_reset(pll);
-       if (r)
-               return r;
-
-       r = hdmi_pll_config(pll);
-       if (r)
-               return r;
-
        return 0;
 }
 
-void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
+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;
+
        hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
 }
 
-static const struct hdmi_pll_features omap44xx_pll_feats = {
-       .sys_reset              =       false,
-       .bound_dcofreq          =       false,
-       .fint_min               =       500000,
-       .fint_max               =       2500000,
-       .regm_max               =       4095,
-       .dcofreq_low_min        =       500000000,
-       .dcofreq_low_max        =       1000000000,
-       .dcofreq_high_min       =       1000000000,
-       .dcofreq_high_max       =       2000000000,
+static const struct dss_pll_ops dsi_pll_ops = {
+       .enable = hdmi_pll_enable,
+       .disable = hdmi_pll_disable,
+       .set_config = dss_pll_write_config_type_b,
 };
 
-static const struct hdmi_pll_features omap54xx_pll_feats = {
-       .sys_reset              =       true,
-       .bound_dcofreq          =       true,
-       .fint_min               =       620000,
-       .fint_max               =       2500000,
-       .regm_max               =       2046,
-       .dcofreq_low_min        =       750000000,
-       .dcofreq_low_max        =       1500000000,
-       .dcofreq_high_min       =       1250000000,
-       .dcofreq_high_max       =       2500000000UL,
+static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
+       .n_max = 255,
+       .m_min = 20,
+       .m_max = 4095,
+       .mX_max = 127,
+       .fint_min = 500000,
+       .fint_max = 2500000,
+       .clkdco_max = 1800000000,
+
+       .clkdco_min = 500000000,
+       .clkdco_low = 1000000000,
+       .clkdco_max = 2000000000,
+
+       .n_msb = 8,
+       .n_lsb = 1,
+       .m_msb = 20,
+       .m_lsb = 9,
+
+       .mX_msb[0] = 24,
+       .mX_lsb[0] = 18,
+
+       .has_selfreqdco = true,
 };
 
-static int hdmi_pll_init_features(struct platform_device *pdev)
+static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
+       .n_max = 255,
+       .m_min = 20,
+       .m_max = 2045,
+       .mX_max = 127,
+       .fint_min = 620000,
+       .fint_max = 2500000,
+       .clkdco_max = 1800000000,
+
+       .clkdco_min = 750000000,
+       .clkdco_low = 1500000000,
+       .clkdco_max = 2500000000UL,
+
+       .n_msb = 8,
+       .n_lsb = 1,
+       .m_msb = 20,
+       .m_lsb = 9,
+
+       .mX_msb[0] = 24,
+       .mX_lsb[0] = 18,
+
+       .has_selfreqdco = true,
+       .has_refsel = true,
+};
+
+static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data *hpll)
 {
-       struct hdmi_pll_features *dst;
-       const struct hdmi_pll_features *src;
+       struct dss_pll *pll = &hpll->pll;
+       struct clk *clk;
+       int r;
 
-       dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
-       if (!dst) {
-               dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n");
-               return -ENOMEM;
+       clk = devm_clk_get(&pdev->dev, "sys_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get sys_clk\n");
+               return PTR_ERR(clk);
        }
 
+       pll->name = "hdmi";
+       pll->base = hpll->base;
+       pll->clkin = clk;
+
        switch (omapdss_get_version()) {
        case OMAPDSS_VER_OMAP4430_ES1:
        case OMAPDSS_VER_OMAP4430_ES2:
        case OMAPDSS_VER_OMAP4:
-               src = &omap44xx_pll_feats;
+               pll->hw = &dss_omap4_hdmi_pll_hw;
                break;
 
        case OMAPDSS_VER_OMAP5:
-               src = &omap54xx_pll_feats;
+               pll->hw = &dss_omap5_hdmi_pll_hw;
                break;
 
        default:
                return -ENODEV;
        }
 
-       memcpy(dst, src, sizeof(*dst));
-       pll_feat = dst;
+       pll->ops = &dsi_pll_ops;
+
+       r = dss_pll_register(pll);
+       if (r)
+               return r;
 
        return 0;
 }
 
-int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
+int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
+       struct hdmi_wp_data *wp)
 {
        int r;
        struct resource *res;
 
-       r = hdmi_pll_init_features(pdev);
-       if (r)
-               return r;
+       pll->wp = wp;
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
        if (!res) {
@@ -286,5 +234,18 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
                return PTR_ERR(pll->base);
        }
 
+       r = dsi_init_pll_data(pdev, pll);
+       if (r) {
+               DSSERR("failed to init HDMI PLL\n");
+               return r;
+       }
+
        return 0;
 }
+
+void hdmi_pll_uninit(struct hdmi_pll_data *hpll)
+{
+       struct dss_pll *pll = &hpll->pll;
+
+       dss_pll_unregister(pll);
+}
index 496327e2b21b877b4448e90fe47478f772d41871..c15377e242cc44244b90f517c63c78fcf9412c62 100644 (file)
@@ -185,7 +185,6 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
        timings->interlace = param->timings.interlace;
 }
 
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
 void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
                struct hdmi_audio_format *aud_fmt)
 {
@@ -194,8 +193,12 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
        DSSDBG("Enter hdmi_wp_audio_config_format\n");
 
        r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
-       r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
-       r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
+       if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 ||
+           omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||
+           omapdss_get_version() == OMAPDSS_VER_OMAP4) {
+               r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
+               r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
+       }
        r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
        r = FLD_MOD(r, aud_fmt->type, 4, 4);
        r = FLD_MOD(r, aud_fmt->justification, 3, 3);
@@ -236,7 +239,6 @@ int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
 
        return 0;
 }
-#endif
 
 int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
 {
@@ -247,6 +249,7 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
                DSSERR("can't get WP mem resource\n");
                return -EINVAL;
        }
+       wp->phys_base = res->start;
 
        wp->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(wp->base)) {
@@ -256,3 +259,8 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
 
        return 0;
 }
+
+phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp)
+{
+       return wp->phys_base + HDMI_WP_AUDIO_DATA;
+}
index 2ab3afa615e8dc4e7316700f94d69eb638381ea5..16072159bd24344731f03a413459a4c290793d7e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <video/omapdss.h>
 
@@ -131,18 +132,30 @@ struct omap_dss_device *omap_dss_find_output(const char *name)
 }
 EXPORT_SYMBOL(omap_dss_find_output);
 
-struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node)
+struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port)
 {
+       struct device_node *src_node;
        struct omap_dss_device *out;
+       u32 reg;
+
+       src_node = dss_of_port_get_parent_device(port);
+       if (!src_node)
+               return NULL;
+
+       reg = dss_of_port_get_port_number(port);
 
        list_for_each_entry(out, &output_list, list) {
-               if (out->dev->of_node == node)
+               if (out->dev->of_node == src_node && out->port_num == reg) {
+                       of_node_put(src_node);
                        return omap_dss_get_device(out);
+               }
        }
 
+       of_node_put(src_node);
+
        return NULL;
 }
-EXPORT_SYMBOL(omap_dss_find_output_by_node);
+EXPORT_SYMBOL(omap_dss_find_output_by_port_node);
 
 struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
 {
diff --git a/drivers/video/fbdev/omap2/dss/pll.c b/drivers/video/fbdev/omap2/dss/pll.c
new file mode 100644 (file)
index 0000000..50bc62c
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2014 Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "PLL"
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/regulator/consumer.h>
+#include <linux/sched.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+
+#define PLL_CONTROL                    0x0000
+#define PLL_STATUS                     0x0004
+#define PLL_GO                         0x0008
+#define PLL_CONFIGURATION1             0x000C
+#define PLL_CONFIGURATION2             0x0010
+#define PLL_CONFIGURATION3             0x0014
+#define PLL_SSC_CONFIGURATION1         0x0018
+#define PLL_SSC_CONFIGURATION2         0x001C
+#define PLL_CONFIGURATION4             0x0020
+
+static struct dss_pll *dss_plls[4];
+
+int dss_pll_register(struct dss_pll *pll)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
+               if (!dss_plls[i]) {
+                       dss_plls[i] = pll;
+                       return 0;
+               }
+       }
+
+       return -EBUSY;
+}
+
+void dss_pll_unregister(struct dss_pll *pll)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
+               if (dss_plls[i] == pll) {
+                       dss_plls[i] = NULL;
+                       return;
+               }
+       }
+}
+
+struct dss_pll *dss_pll_find(const char *name)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
+               if (dss_plls[i] && strcmp(dss_plls[i]->name, name) == 0)
+                       return dss_plls[i];
+       }
+
+       return NULL;
+}
+
+int dss_pll_enable(struct dss_pll *pll)
+{
+       int r;
+
+       r = clk_prepare_enable(pll->clkin);
+       if (r)
+               return r;
+
+       if (pll->regulator) {
+               r = regulator_enable(pll->regulator);
+               if (r)
+                       goto err_reg;
+       }
+
+       r = pll->ops->enable(pll);
+       if (r)
+               goto err_enable;
+
+       return 0;
+
+err_enable:
+       regulator_disable(pll->regulator);
+err_reg:
+       clk_disable_unprepare(pll->clkin);
+       return r;
+}
+
+void dss_pll_disable(struct dss_pll *pll)
+{
+       pll->ops->disable(pll);
+
+       if (pll->regulator)
+               regulator_disable(pll->regulator);
+
+       clk_disable_unprepare(pll->clkin);
+
+       memset(&pll->cinfo, 0, sizeof(pll->cinfo));
+}
+
+int dss_pll_set_config(struct dss_pll *pll, const struct dss_pll_clock_info *cinfo)
+{
+       int r;
+
+       r = pll->ops->set_config(pll, cinfo);
+       if (r)
+               return r;
+
+       pll->cinfo = *cinfo;
+
+       return 0;
+}
+
+bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
+               unsigned long out_min, unsigned long out_max,
+               dss_hsdiv_calc_func func, void *data)
+{
+       const struct dss_pll_hw *hw = pll->hw;
+       int m, m_start, m_stop;
+       unsigned long out;
+
+       out_min = out_min ? out_min : 1;
+       out_max = out_max ? out_max : ULONG_MAX;
+
+       m_start = max(DIV_ROUND_UP(clkdco, out_max), 1ul);
+
+       m_stop = min((unsigned)(clkdco / out_min), hw->mX_max);
+
+       for (m = m_start; m <= m_stop; ++m) {
+               out = clkdco / m;
+
+               if (func(m, out, data))
+                       return true;
+       }
+
+       return false;
+}
+
+bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
+               unsigned long pll_min, unsigned long pll_max,
+               dss_pll_calc_func func, void *data)
+{
+       const struct dss_pll_hw *hw = pll->hw;
+       int n, n_start, n_stop;
+       int m, m_start, m_stop;
+       unsigned long fint, clkdco;
+       unsigned long pll_hw_max;
+       unsigned long fint_hw_min, fint_hw_max;
+
+       pll_hw_max = hw->clkdco_max;
+
+       fint_hw_min = hw->fint_min;
+       fint_hw_max = hw->fint_max;
+
+       n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
+       n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
+
+       pll_max = pll_max ? pll_max : ULONG_MAX;
+
+       for (n = n_start; n <= n_stop; ++n) {
+               fint = clkin / n;
+
+               m_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
+                               1ul);
+               m_stop = min3((unsigned)(pll_max / fint / 2),
+                               (unsigned)(pll_hw_max / fint / 2),
+                               hw->m_max);
+
+               for (m = m_start; m <= m_stop; ++m) {
+                       clkdco = 2 * m * fint;
+
+                       if (func(n, m, fint, clkdco, data))
+                               return true;
+               }
+       }
+
+       return false;
+}
+
+static int wait_for_bit_change(void __iomem *reg, int bitnum, int value)
+{
+       unsigned long timeout;
+       ktime_t wait;
+       int t;
+
+       /* first busyloop to see if the bit changes right away */
+       t = 100;
+       while (t-- > 0) {
+               if (FLD_GET(readl_relaxed(reg), bitnum, bitnum) == value)
+                       return value;
+       }
+
+       /* then loop for 500ms, sleeping for 1ms in between */
+       timeout = jiffies + msecs_to_jiffies(500);
+       while (time_before(jiffies, timeout)) {
+               if (FLD_GET(readl_relaxed(reg), bitnum, bitnum) == value)
+                       return value;
+
+               wait = ns_to_ktime(1000 * 1000);
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
+       }
+
+       return !value;
+}
+
+static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask)
+{
+       int t = 100;
+
+       while (t-- > 0) {
+               u32 v = readl_relaxed(pll->base + PLL_STATUS);
+               v &= hsdiv_ack_mask;
+               if (v == hsdiv_ack_mask)
+                       return 0;
+       }
+
+       return -ETIMEDOUT;
+}
+
+int dss_pll_write_config_type_a(struct dss_pll *pll,
+               const struct dss_pll_clock_info *cinfo)
+{
+       const struct dss_pll_hw *hw = pll->hw;
+       void __iomem *base = pll->base;
+       int r = 0;
+       u32 l;
+
+       l = 0;
+       if (hw->has_stopmode)
+               l = FLD_MOD(l, 1, 0, 0);                /* PLL_STOPMODE */
+       l = FLD_MOD(l, cinfo->n - 1, hw->n_msb, hw->n_lsb);     /* PLL_REGN */
+       l = FLD_MOD(l, cinfo->m, hw->m_msb, hw->m_lsb);         /* PLL_REGM */
+       /* M4 */
+       l = FLD_MOD(l, cinfo->mX[0] ? cinfo->mX[0] - 1 : 0,
+                       hw->mX_msb[0], hw->mX_lsb[0]);
+       /* M5 */
+       l = FLD_MOD(l, cinfo->mX[1] ? cinfo->mX[1] - 1 : 0,
+                       hw->mX_msb[1], hw->mX_lsb[1]);
+       writel_relaxed(l, base + PLL_CONFIGURATION1);
+
+       l = 0;
+       /* M6 */
+       l = FLD_MOD(l, cinfo->mX[2] ? cinfo->mX[2] - 1 : 0,
+                       hw->mX_msb[2], hw->mX_lsb[2]);
+       /* M7 */
+       l = FLD_MOD(l, cinfo->mX[3] ? cinfo->mX[3] - 1 : 0,
+                       hw->mX_msb[3], hw->mX_lsb[3]);
+       writel_relaxed(l, base + PLL_CONFIGURATION3);
+
+       l = readl_relaxed(base + PLL_CONFIGURATION2);
+       if (hw->has_freqsel) {
+               u32 f = cinfo->fint < 1000000 ? 0x3 :
+                       cinfo->fint < 1250000 ? 0x4 :
+                       cinfo->fint < 1500000 ? 0x5 :
+                       cinfo->fint < 1750000 ? 0x6 :
+                       0x7;
+
+               l = FLD_MOD(l, f, 4, 1);        /* PLL_FREQSEL */
+       } else if (hw->has_selfreqdco) {
+               u32 f = cinfo->clkdco < hw->clkdco_low ? 0x2 : 0x4;
+
+               l = FLD_MOD(l, f, 3, 1);        /* PLL_SELFREQDCO */
+       }
+       l = FLD_MOD(l, 1, 13, 13);              /* PLL_REFEN */
+       l = FLD_MOD(l, 0, 14, 14);              /* PHY_CLKINEN */
+       l = FLD_MOD(l, 0, 16, 16);              /* M4_CLOCK_EN */
+       l = FLD_MOD(l, 0, 18, 18);              /* M5_CLOCK_EN */
+       l = FLD_MOD(l, 1, 20, 20);              /* HSDIVBYPASS */
+       if (hw->has_refsel)
+               l = FLD_MOD(l, 3, 22, 21);      /* REFSEL = sysclk */
+       l = FLD_MOD(l, 0, 23, 23);              /* M6_CLOCK_EN */
+       l = FLD_MOD(l, 0, 25, 25);              /* M7_CLOCK_EN */
+       writel_relaxed(l, base + PLL_CONFIGURATION2);
+
+       writel_relaxed(1, base + PLL_GO);       /* PLL_GO */
+
+       if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
+               DSSERR("DSS DPLL GO bit not going down.\n");
+               r = -EIO;
+               goto err;
+       }
+
+       if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) {
+               DSSERR("cannot lock DSS DPLL\n");
+               r = -EIO;
+               goto err;
+       }
+
+       l = readl_relaxed(base + PLL_CONFIGURATION2);
+       l = FLD_MOD(l, 1, 14, 14);                      /* PHY_CLKINEN */
+       l = FLD_MOD(l, cinfo->mX[0] ? 1 : 0, 16, 16);   /* M4_CLOCK_EN */
+       l = FLD_MOD(l, cinfo->mX[1] ? 1 : 0, 18, 18);   /* M5_CLOCK_EN */
+       l = FLD_MOD(l, 0, 20, 20);                      /* HSDIVBYPASS */
+       l = FLD_MOD(l, cinfo->mX[2] ? 1 : 0, 23, 23);   /* M6_CLOCK_EN */
+       l = FLD_MOD(l, cinfo->mX[3] ? 1 : 0, 25, 25);   /* M7_CLOCK_EN */
+       writel_relaxed(l, base + PLL_CONFIGURATION2);
+
+       r = dss_wait_hsdiv_ack(pll,
+               (cinfo->mX[0] ? BIT(7) : 0) |
+               (cinfo->mX[1] ? BIT(8) : 0) |
+               (cinfo->mX[2] ? BIT(10) : 0) |
+               (cinfo->mX[3] ? BIT(11) : 0));
+       if (r) {
+               DSSERR("failed to enable HSDIV clocks\n");
+               goto err;
+       }
+
+err:
+       return r;
+}
+
+int dss_pll_write_config_type_b(struct dss_pll *pll,
+               const struct dss_pll_clock_info *cinfo)
+{
+       const struct dss_pll_hw *hw = pll->hw;
+       void __iomem *base = pll->base;
+       u32 l;
+
+       l = 0;
+       l = FLD_MOD(l, cinfo->m, 20, 9);        /* PLL_REGM */
+       l = FLD_MOD(l, cinfo->n - 1, 8, 1);     /* PLL_REGN */
+       writel_relaxed(l, base + PLL_CONFIGURATION1);
+
+       l = readl_relaxed(base + PLL_CONFIGURATION2);
+       l = FLD_MOD(l, 0x0, 12, 12);    /* PLL_HIGHFREQ divide by 2 */
+       l = FLD_MOD(l, 0x1, 13, 13);    /* PLL_REFEN */
+       l = FLD_MOD(l, 0x0, 14, 14);    /* PHY_CLKINEN */
+       if (hw->has_refsel)
+               l = FLD_MOD(l, 0x3, 22, 21);    /* REFSEL = SYSCLK */
+
+       /* PLL_SELFREQDCO */
+       if (cinfo->clkdco > hw->clkdco_low)
+               l = FLD_MOD(l, 0x4, 3, 1);
+       else
+               l = FLD_MOD(l, 0x2, 3, 1);
+       writel_relaxed(l, base + PLL_CONFIGURATION2);
+
+       l = readl_relaxed(base + PLL_CONFIGURATION3);
+       l = FLD_MOD(l, cinfo->sd, 17, 10);      /* PLL_REGSD */
+       writel_relaxed(l, base + PLL_CONFIGURATION3);
+
+       l = readl_relaxed(base + PLL_CONFIGURATION4);
+       l = FLD_MOD(l, cinfo->mX[0], 24, 18);   /* PLL_REGM2 */
+       l = FLD_MOD(l, cinfo->mf, 17, 0);       /* PLL_REGM_F */
+       writel_relaxed(l, base + PLL_CONFIGURATION4);
+
+       writel_relaxed(1, base + PLL_GO);       /* PLL_GO */
+
+       if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
+               DSSERR("DSS DPLL GO bit not going down.\n");
+               return -EIO;
+       }
+
+       if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) {
+               DSSERR("cannot lock DSS DPLL\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
index 4c9c46d4ea60dbe2752c11f1933af4788ff41559..d9b10f27be201338ae38052da3771233db6b2090 100644 (file)
@@ -425,7 +425,7 @@ err_datapairs:
        return r;
 }
 
-void __exit sdi_uninit_port(void)
+void __exit sdi_uninit_port(struct device_node *port)
 {
        if (!sdi.port_initialized)
                return;
index c43b969e1e23c98f88f348b118fa4c462afdab9c..f0ae61a37f047056185ed2deeb9d01d650c8083b 100644 (file)
@@ -1182,7 +1182,7 @@ static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
 
-       par->state.vgabase = (void __iomem *) vga_res.start;
+       par->state.vgabase = (void __iomem *) (unsigned long) vga_res.start;
 
        /* Unlock regs */
        cr38 = vga_rcrt(par->state.vgabase, 0x38);
index 2bcc84ac18c762f7bc7f5acecdb34149192a1308..cfde21d81c15e3f76d5d73f7ad55105c6f4416fc 100644 (file)
@@ -2181,8 +2181,7 @@ sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
        if (!info || !info->device)
                return;
 
-       if (ch->sglist)
-               vfree(ch->sglist);
+       vfree(ch->sglist);
 
        fb_dealloc_cmap(&info->cmap);
        framebuffer_release(info);
index e5d11b1892e8be74166ef63a3d3585ef98c463cc..fcf610edf217b83a18f0216deba34fb4c416c835 100644 (file)
@@ -5989,7 +5989,7 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if(!ivideo->sisvga_enabled) {
                if(pci_enable_device(pdev)) {
-                       if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
+                       pci_dev_put(ivideo->nbridge);
                        framebuffer_release(sis_fb_info);
                        return -EIO;
                }
@@ -6202,10 +6202,8 @@ error_0: iounmap(ivideo->video_vbase);
 error_1:       release_mem_region(ivideo->video_base, ivideo->video_size);
 error_2:       release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 error_3:       vfree(ivideo->bios_abase);
-               if(ivideo->lpcdev)
-                       pci_dev_put(ivideo->lpcdev);
-               if(ivideo->nbridge)
-                       pci_dev_put(ivideo->nbridge);
+               pci_dev_put(ivideo->lpcdev);
+               pci_dev_put(ivideo->nbridge);
                if(!ivideo->sisvga_enabled)
                        pci_disable_device(pdev);
                framebuffer_release(sis_fb_info);
@@ -6505,11 +6503,9 @@ static void sisfb_remove(struct pci_dev *pdev)
 
        vfree(ivideo->bios_abase);
 
-       if(ivideo->lpcdev)
-               pci_dev_put(ivideo->lpcdev);
+       pci_dev_put(ivideo->lpcdev);
 
-       if(ivideo->nbridge)
-               pci_dev_put(ivideo->nbridge);
+       pci_dev_put(ivideo->nbridge);
 
 #ifdef CONFIG_MTRR
        /* Release MTRR region */
index 9e74e8fbe074015c7ee149104edf6826424a87a3..8b98b011fc046bcae5ab05bb147a51fb517878f9 100644 (file)
@@ -1988,6 +1988,7 @@ static int sm501fb_probe(struct platform_device *pdev)
        if (info->fb[HEAD_PANEL] == NULL &&
            info->fb[HEAD_CRT] == NULL) {
                dev_err(dev, "no framebuffers found\n");
+               ret = -ENODEV;
                goto err_alloc;
        }
 
index d513ed6a49f2ec3fdf5b9786879d7f65f8e780c0..9279e5f6696e24ad84ea11a5e3adf7c1980c9a91 100644 (file)
@@ -1142,8 +1142,7 @@ static void ufx_free_framebuffer_work(struct work_struct *work)
                fb_dealloc_cmap(&info->cmap);
        if (info->monspecs.modedb)
                fb_destroy_modedb(info->monspecs.modedb);
-       if (info->screen_base)
-               vfree(info->screen_base);
+       vfree(info->screen_base);
 
        fb_destroy_modelist(&info->modelist);
 
@@ -1743,8 +1742,7 @@ error:
                                fb_dealloc_cmap(&info->cmap);
                        if (info->monspecs.modedb)
                                fb_destroy_modedb(info->monspecs.modedb);
-                       if (info->screen_base)
-                               vfree(info->screen_base);
+                       vfree(info->screen_base);
 
                        fb_destroy_modelist(&info->modelist);
 
index 046d51d83d7475c9eabe58db3dc779db028cc440..ff2b8731a2dc6781d1aacb747609cb1a31f05223 100644 (file)
@@ -922,8 +922,7 @@ static void dlfb_free(struct kref *kref)
 {
        struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
 
-       if (dev->backing_buffer)
-               vfree(dev->backing_buffer);
+       vfree(dev->backing_buffer);
 
        kfree(dev->edid);
 
@@ -953,8 +952,7 @@ static void dlfb_free_framebuffer(struct dlfb_data *dev)
                        fb_dealloc_cmap(&info->cmap);
                if (info->monspecs.modedb)
                        fb_destroy_modedb(info->monspecs.modedb);
-               if (info->screen_base)
-                       vfree(info->screen_base);
+               vfree(info->screen_base);
 
                fb_destroy_modelist(&info->modelist);
 
@@ -1203,8 +1201,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
                if (!new_back)
                        pr_info("No shadow/backing buffer allocated\n");
                else {
-                       if (dev->backing_buffer)
-                               vfree(dev->backing_buffer);
+                       vfree(dev->backing_buffer);
                        dev->backing_buffer = new_back;
                }
        }
index 509d452e8f91f8ed2181cf148139305deccb60a8..d32d1c4d1b99f81a1962bb92bf7cc6b3e1ad77ff 100644 (file)
@@ -1219,8 +1219,7 @@ static int uvesafb_release(struct fb_info *info, int user)
        uvesafb_vbe_state_restore(par, par->vbe_state_orig);
 out:
        atomic_dec(&par->ref_count);
-       if (task)
-               uvesafb_free(task);
+       uvesafb_free(task);
        return 0;
 }
 
@@ -1923,8 +1922,7 @@ static int uvesafb_init(void)
                        err = -ENOMEM;
 
                if (err) {
-                       if (uvesafb_device)
-                               platform_device_put(uvesafb_device);
+                       platform_device_put(uvesafb_device);
                        platform_driver_unregister(&uvesafb_driver);
                        cn_del_callback(&uvesafb_cn_id);
                        return err;
index 325c43c6ff973895eb6b4b573b330ad596295a6a..f9718f012aae9be85a9568a2ce7be0740f08f5f6 100644 (file)
@@ -1937,8 +1937,7 @@ out_fb1_unreg_lcd_cle266:
 out_dealloc_cmap:
        fb_dealloc_cmap(&viafbinfo->cmap);
 out_fb1_release:
-       if (viafbinfo1)
-               framebuffer_release(viafbinfo1);
+       framebuffer_release(viafbinfo1);
 out_fb_release:
        i2c_bus_free(viaparinfo->shared);
        framebuffer_release(viafbinfo);
index 5c7cbc6c62360a3154e19c861ea8eb1374f04c14..ea7f056ed5fe3c4bbc04c45d9e09043bf7f134ce 100644 (file)
@@ -731,7 +731,7 @@ static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
 
-       par->state.vgabase = (void __iomem *) vga_res.start;
+       par->state.vgabase = (void __iomem *) (unsigned long) vga_res.start;
 
        /* Find how many physical memory there is on card */
        memsize1 = (vga_rseq(par->state.vgabase, 0x34) + 1) >> 1;
diff --git a/include/sound/omap-hdmi-audio.h b/include/sound/omap-hdmi-audio.h
new file mode 100644 (file)
index 0000000..afdb416
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * hdmi-audio.c -- OMAP4+ DSS HDMI audio support library
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Jyri Sarha <jsarha@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <video/omapdss.h>
+
+#ifndef __OMAP_HDMI_AUDIO_H__
+#define __OMAP_HDMI_AUDIO_H__
+
+struct omap_hdmi_audio_ops {
+       int (*audio_startup)(struct device *dev,
+                            void (*abort_cb)(struct device *dev));
+       int (*audio_shutdown)(struct device *dev);
+       int (*audio_start)(struct device *dev);
+       void (*audio_stop)(struct device *dev);
+       int (*audio_config)(struct device *dev,
+                           struct omap_dss_audio *dss_audio);
+};
+
+/* HDMI audio initalization data */
+struct omap_hdmi_audio_pdata {
+       struct device *dev;
+       enum omapdss_version dss_version;
+       phys_addr_t audio_dma_addr;
+
+       const struct omap_hdmi_audio_ops *ops;
+};
+
+#endif /* __OMAP_HDMI_AUDIO_H__ */
index 069dfca9549af5808bf39c261fe89701673175f0..6a84498ea5135babb4cc7341173e5f176cf88704 100644 (file)
@@ -166,13 +166,6 @@ enum omap_dss_display_state {
        OMAP_DSS_DISPLAY_ACTIVE,
 };
 
-enum omap_dss_audio_state {
-       OMAP_DSS_AUDIO_DISABLED = 0,
-       OMAP_DSS_AUDIO_ENABLED,
-       OMAP_DSS_AUDIO_CONFIGURED,
-       OMAP_DSS_AUDIO_PLAYING,
-};
-
 struct omap_dss_audio {
        struct snd_aes_iec958 *iec;
        struct snd_cea_861_aud_if *cea;
@@ -635,19 +628,6 @@ struct omapdss_hdmi_ops {
        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);
-
-       /*
-        * Note: These functions might sleep. Do not call while
-        * holding a spinlock/readlock.
-        */
-       int (*audio_enable)(struct omap_dss_device *dssdev);
-       void (*audio_disable)(struct omap_dss_device *dssdev);
-       bool (*audio_supported)(struct omap_dss_device *dssdev);
-       int (*audio_config)(struct omap_dss_device *dssdev,
-               struct omap_dss_audio *audio);
-       /* Note: These functions may not sleep */
-       int (*audio_start)(struct omap_dss_device *dssdev);
-       void (*audio_stop)(struct omap_dss_device *dssdev);
 };
 
 struct omapdss_dsi_ops {
@@ -783,8 +763,6 @@ struct omap_dss_device {
 
        enum omap_dss_display_state state;
 
-       enum omap_dss_audio_state audio_state;
-
        /* OMAP DSS output specific fields */
 
        struct list_head list;
@@ -795,6 +773,9 @@ struct omap_dss_device {
        /* 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;
 
@@ -858,24 +839,6 @@ struct omap_dss_driver {
        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);
-
-       /*
-        * For display drivers that support audio. This encompasses
-        * HDMI and DisplayPort at the moment.
-        */
-       /*
-        * Note: These functions might sleep. Do not call while
-        * holding a spinlock/readlock.
-        */
-       int (*audio_enable)(struct omap_dss_device *dssdev);
-       void (*audio_disable)(struct omap_dss_device *dssdev);
-       bool (*audio_supported)(struct omap_dss_device *dssdev);
-       int (*audio_config)(struct omap_dss_device *dssdev,
-               struct omap_dss_audio *audio);
-       /* Note: These functions may not sleep */
-       int (*audio_start)(struct omap_dss_device *dssdev);
-       void (*audio_stop)(struct omap_dss_device *dssdev);
-
 };
 
 enum omapdss_version omapdss_get_version(void);
@@ -918,7 +881,7 @@ 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_node(struct device_node *node);
+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);
index d44463a7b0faed8faef4565657962111604daa2c..3dfcadf00e55c843c38526786feb9df446755745 100644 (file)
@@ -12,8 +12,20 @@ config SND_OMAP_SOC_MCBSP
 config SND_OMAP_SOC_MCPDM
        tristate
 
-config SND_OMAP_SOC_HDMI
-       tristate
+config SND_OMAP_SOC_HDMI_AUDIO
+       tristate "HDMI audio support for OMAP4+ based SoCs"
+       depends on SND_OMAP_SOC
+       help
+         For HDMI audio to work OMAPDSS HDMI support should be
+         enabled.
+         The hdmi audio driver implements cpu-dai component using the
+         callbacks provided by OMAPDSS and registers the component
+         under DSS HDMI device. Omap-pcm is registered for platform
+         component also under DSS HDMI device. Dummy codec is used as
+         as codec component. The hdmi audio driver implements also
+         the card and registers it under its own platform device.
+         The device for the dirver is registered by OMAPDSS hdmi
+         driver.
 
 config SND_OMAP_SOC_N810
        tristate "SoC Audio support for Nokia N810"
@@ -100,16 +112,6 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040
          - PandaBoard (4430)
          - PandaBoardES (4460)
 
-config SND_OMAP_SOC_OMAP_HDMI
-       tristate "SoC Audio support for Texas Instruments OMAP HDMI"
-       depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS
-       select SND_OMAP_SOC_HDMI
-       select SND_SOC_HDMI_CODEC
-       select OMAP4_DSS_HDMI_AUDIO
-       help
-         Say Y if you want to add support for SoC HDMI audio on Texas Instruments
-         OMAP4 chips
-
 config SND_OMAP_SOC_OMAP3_PANDORA
        tristate "SoC Audio support for OMAP3 Pandora"
        depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
index a725905b2c68b7c8041389b4d84cffa4bb5c2f49..db36fbd5d1a08a9be7c18bcccff7673e6de3a41e 100644 (file)
@@ -3,13 +3,13 @@ snd-soc-omap-objs := omap-pcm.o
 snd-soc-omap-dmic-objs := omap-dmic.o
 snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o
 snd-soc-omap-mcpdm-objs := omap-mcpdm.o
-snd-soc-omap-hdmi-objs := omap-hdmi.o
+snd-soc-omap-hdmi-audio-objs := omap-hdmi-audio.o
 
 obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
 obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o
 obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
 obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
-obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
+obj-$(CONFIG_SND_OMAP_SOC_HDMI_AUDIO) += snd-soc-omap-hdmi-audio.o
 
 # OMAP Machine Support
 snd-soc-n810-objs := n810.o
@@ -20,7 +20,6 @@ snd-soc-am3517evm-objs := am3517evm.o
 snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o
 snd-soc-omap-twl4030-objs := omap-twl4030.o
 snd-soc-omap3pandora-objs := omap3pandora.o
-snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o
 
 obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
 obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
@@ -30,4 +29,3 @@ obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
-obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c
new file mode 100644 (file)
index 0000000..3f9ac7d
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * omap-hdmi-audio.c -- OMAP4+ DSS HDMI audio support library
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Jyri Sarha <jsarha@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+#include <uapi/sound/asound.h>
+#include <sound/asoundef.h>
+#include <sound/omap-pcm.h>
+#include <sound/omap-hdmi-audio.h>
+#include <video/omapdss.h>
+
+#define DRV_NAME "omap-hdmi-audio"
+
+struct hdmi_audio_data {
+       struct snd_soc_card *card;
+
+       const struct omap_hdmi_audio_ops *ops;
+       struct device *dssdev;
+       struct snd_dmaengine_dai_dma_data dma_data;
+       struct omap_dss_audio dss_audio;
+       struct snd_aes_iec958 iec;
+       struct snd_cea_861_aud_if cea;
+
+       struct mutex current_stream_lock;
+       struct snd_pcm_substream *current_stream;
+};
+
+static
+struct hdmi_audio_data *card_drvdata_substream(struct snd_pcm_substream *ss)
+{
+       struct snd_soc_pcm_runtime *rtd = ss->private_data;
+
+       return snd_soc_card_get_drvdata(rtd->card);
+}
+
+static void hdmi_dai_abort(struct device *dev)
+{
+       struct hdmi_audio_data *ad = dev_get_drvdata(dev);
+
+       mutex_lock(&ad->current_stream_lock);
+       if (ad->current_stream && ad->current_stream->runtime &&
+           snd_pcm_running(ad->current_stream)) {
+               dev_err(dev, "HDMI display disabled, aborting playback\n");
+               snd_pcm_stream_lock_irq(ad->current_stream);
+               snd_pcm_stop(ad->current_stream, SNDRV_PCM_STATE_DISCONNECTED);
+               snd_pcm_stream_unlock_irq(ad->current_stream);
+       }
+       mutex_unlock(&ad->current_stream_lock);
+}
+
+static int hdmi_dai_startup(struct snd_pcm_substream *substream,
+                           struct snd_soc_dai *dai)
+{
+       struct hdmi_audio_data *ad = card_drvdata_substream(substream);
+       int ret;
+       /*
+        * Make sure that the period bytes are multiple of the DMA packet size.
+        * Largest packet size we use is 32 32-bit words = 128 bytes
+        */
+       ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+       if (ret < 0) {
+               dev_err(dai->dev, "could not apply constraint\n");
+               return ret;
+       }
+
+       snd_soc_dai_set_dma_data(dai, substream, &ad->dma_data);
+
+       mutex_lock(&ad->current_stream_lock);
+       ad->current_stream = substream;
+       mutex_unlock(&ad->current_stream_lock);
+
+       ret = ad->ops->audio_startup(ad->dssdev, hdmi_dai_abort);
+
+       if (ret) {
+               mutex_lock(&ad->current_stream_lock);
+               ad->current_stream = NULL;
+               mutex_unlock(&ad->current_stream_lock);
+       }
+
+       return ret;
+}
+
+static int hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params,
+                             struct snd_soc_dai *dai)
+{
+       struct hdmi_audio_data *ad = card_drvdata_substream(substream);
+       struct snd_aes_iec958 *iec = &ad->iec;
+       struct snd_cea_861_aud_if *cea = &ad->cea;
+
+       WARN_ON(ad->current_stream != substream);
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               ad->dma_data.maxburst = 16;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               ad->dma_data.maxburst = 32;
+               break;
+       default:
+               dev_err(dai->dev, "format not supported!\n");
+               return -EINVAL;
+       }
+
+       ad->dss_audio.iec = iec;
+       ad->dss_audio.cea = cea;
+       /*
+        * fill the IEC-60958 channel status word
+        */
+       /* initialize the word bytes */
+       memset(iec->status, 0, sizeof(iec->status));
+
+       /* specify IEC-60958-3 (commercial use) */
+       iec->status[0] &= ~IEC958_AES0_PROFESSIONAL;
+
+       /* specify that the audio is LPCM*/
+       iec->status[0] &= ~IEC958_AES0_NONAUDIO;
+
+       iec->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
+
+       iec->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE;
+
+       iec->status[0] |= IEC958_AES1_PRO_MODE_NOTID;
+
+       iec->status[1] = IEC958_AES1_CON_GENERAL;
+
+       iec->status[2] |= IEC958_AES2_CON_SOURCE_UNSPEC;
+
+       iec->status[2] |= IEC958_AES2_CON_CHANNEL_UNSPEC;
+
+       switch (params_rate(params)) {
+       case 32000:
+               iec->status[3] |= IEC958_AES3_CON_FS_32000;
+               break;
+       case 44100:
+               iec->status[3] |= IEC958_AES3_CON_FS_44100;
+               break;
+       case 48000:
+               iec->status[3] |= IEC958_AES3_CON_FS_48000;
+               break;
+       case 88200:
+               iec->status[3] |= IEC958_AES3_CON_FS_88200;
+               break;
+       case 96000:
+               iec->status[3] |= IEC958_AES3_CON_FS_96000;
+               break;
+       case 176400:
+               iec->status[3] |= IEC958_AES3_CON_FS_176400;
+               break;
+       case 192000:
+               iec->status[3] |= IEC958_AES3_CON_FS_192000;
+               break;
+       default:
+               dev_err(dai->dev, "rate not supported!\n");
+               return -EINVAL;
+       }
+
+       /* specify the clock accuracy */
+       iec->status[3] |= IEC958_AES3_CON_CLOCK_1000PPM;
+
+       /*
+        * specify the word length. The same word length value can mean
+        * two different lengths. Hence, we need to specify the maximum
+        * word length as well.
+        */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               iec->status[4] |= IEC958_AES4_CON_WORDLEN_20_16;
+               iec->status[4] &= ~IEC958_AES4_CON_MAX_WORDLEN_24;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iec->status[4] |= IEC958_AES4_CON_WORDLEN_24_20;
+               iec->status[4] |= IEC958_AES4_CON_MAX_WORDLEN_24;
+               break;
+       default:
+               dev_err(dai->dev, "format not supported!\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Fill the CEA-861 audio infoframe (see spec for details)
+        */
+
+       cea->db1_ct_cc = (params_channels(params) - 1)
+               & CEA861_AUDIO_INFOFRAME_DB1CC;
+       cea->db1_ct_cc |= CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM;
+
+       cea->db2_sf_ss = CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM;
+       cea->db2_sf_ss |= CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM;
+
+       cea->db3 = 0; /* not used, all zeros */
+
+       /*
+        * The OMAP HDMI IP requires to use the 8-channel channel code when
+        * transmitting more than two channels.
+        */
+       if (params_channels(params) == 2)
+               cea->db4_ca = 0x0;
+       else
+               cea->db4_ca = 0x13;
+
+       cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED;
+       /* the expression is trivial but makes clear what we are doing */
+       cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV);
+
+       return ad->ops->audio_config(ad->dssdev, &ad->dss_audio);
+}
+
+static int hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+                           struct snd_soc_dai *dai)
+{
+       struct hdmi_audio_data *ad = card_drvdata_substream(substream);
+       int err = 0;
+
+       WARN_ON(ad->current_stream != substream);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               err = ad->ops->audio_start(ad->dssdev);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               ad->ops->audio_stop(ad->dssdev);
+               break;
+       default:
+               err = -EINVAL;
+       }
+       return err;
+}
+
+static void hdmi_dai_shutdown(struct snd_pcm_substream *substream,
+                             struct snd_soc_dai *dai)
+{
+       struct hdmi_audio_data *ad = card_drvdata_substream(substream);
+
+       WARN_ON(ad->current_stream != substream);
+
+       ad->ops->audio_shutdown(ad->dssdev);
+
+       mutex_lock(&ad->current_stream_lock);
+       ad->current_stream = NULL;
+       mutex_unlock(&ad->current_stream_lock);
+}
+
+static const struct snd_soc_dai_ops hdmi_dai_ops = {
+       .startup        = hdmi_dai_startup,
+       .hw_params      = hdmi_dai_hw_params,
+       .trigger        = hdmi_dai_trigger,
+       .shutdown       = hdmi_dai_shutdown,
+};
+
+static const struct snd_soc_component_driver omap_hdmi_component = {
+       .name = "omapdss_hdmi",
+};
+
+static struct snd_soc_dai_driver omap5_hdmi_dai = {
+       .name = "omap5-hdmi-dai",
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 8,
+               .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                         SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+                         SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                         SNDRV_PCM_RATE_192000),
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops = &hdmi_dai_ops,
+};
+
+static struct snd_soc_dai_driver omap4_hdmi_dai = {
+       .name = "omap4-hdmi-dai",
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 8,
+               .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                         SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+                         SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                         SNDRV_PCM_RATE_192000),
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+       },
+       .ops = &hdmi_dai_ops,
+};
+
+static int omap_hdmi_audio_probe(struct platform_device *pdev)
+{
+       struct omap_hdmi_audio_pdata *ha = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       struct hdmi_audio_data *ad;
+       struct snd_soc_dai_driver *dai_drv;
+       struct snd_soc_card *card;
+       int ret;
+
+       if (!ha) {
+               dev_err(dev, "No platform data\n");
+               return -EINVAL;
+       }
+
+       ad = devm_kzalloc(dev, sizeof(*ad), GFP_KERNEL);
+       if (!ad)
+               return -ENOMEM;
+       ad->dssdev = ha->dev;
+       ad->ops = ha->ops;
+       ad->dma_data.addr = ha->audio_dma_addr;
+       ad->dma_data.filter_data = "audio_tx";
+       ad->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       mutex_init(&ad->current_stream_lock);
+
+       switch (ha->dss_version) {
+       case OMAPDSS_VER_OMAP4430_ES1:
+       case OMAPDSS_VER_OMAP4430_ES2:
+       case OMAPDSS_VER_OMAP4:
+               dai_drv = &omap4_hdmi_dai;
+               break;
+       case OMAPDSS_VER_OMAP5:
+               dai_drv = &omap5_hdmi_dai;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ret = snd_soc_register_component(ad->dssdev, &omap_hdmi_component,
+                                        dai_drv, 1);
+       if (ret)
+               return ret;
+
+       ret = omap_pcm_platform_register(ad->dssdev);
+       if (ret)
+               return ret;
+
+       card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+       card->name = devm_kasprintf(dev, GFP_KERNEL,
+                                   "HDMI %s", dev_name(ad->dssdev));
+       card->owner = THIS_MODULE;
+       card->dai_link =
+               devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL);
+       card->dai_link->name = card->name;
+       card->dai_link->stream_name = card->name;
+       card->dai_link->cpu_dai_name = dev_name(ad->dssdev);
+       card->dai_link->platform_name = dev_name(ad->dssdev);
+       card->dai_link->codec_name = "snd-soc-dummy";
+       card->dai_link->codec_dai_name = "snd-soc-dummy-dai";
+       card->num_links = 1;
+       card->dev = dev;
+
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(dev, "snd_soc_register_card failed (%d)\n", ret);
+               snd_soc_unregister_component(ad->dssdev);
+               return ret;
+       }
+
+       ad->card = card;
+       snd_soc_card_set_drvdata(card, ad);
+
+       dev_set_drvdata(dev, ad);
+
+       return 0;
+}
+
+static int omap_hdmi_audio_remove(struct platform_device *pdev)
+{
+       struct hdmi_audio_data *ad = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(ad->card);
+       snd_soc_unregister_component(ad->dssdev);
+       return 0;
+}
+
+static struct platform_driver hdmi_audio_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = omap_hdmi_audio_probe,
+       .remove = omap_hdmi_audio_remove,
+};
+
+module_platform_driver(hdmi_audio_driver);
+
+MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
+MODULE_DESCRIPTION("OMAP HDMI Audio Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/omap-hdmi-card.c b/sound/soc/omap/omap-hdmi-card.c
deleted file mode 100644 (file)
index f649fe8..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * omap-hdmi-card.c
- *
- * OMAP ALSA SoC machine driver for TI OMAP HDMI
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Ricardo Neri <ricardo.neri@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <asm/mach-types.h>
-#include <video/omapdss.h>
-
-#define DRV_NAME "omap-hdmi-audio"
-
-static struct snd_soc_dai_link omap_hdmi_dai = {
-       .name = "HDMI",
-       .stream_name = "HDMI",
-       .cpu_dai_name = "omap-hdmi-audio-dai",
-       .platform_name = "omap-hdmi-audio-dai",
-       .codec_name = "hdmi-audio-codec",
-       .codec_dai_name = "hdmi-hifi",
-};
-
-static struct snd_soc_card snd_soc_omap_hdmi = {
-       .name = "OMAPHDMI",
-       .owner = THIS_MODULE,
-       .dai_link = &omap_hdmi_dai,
-       .num_links = 1,
-};
-
-static int omap_hdmi_probe(struct platform_device *pdev)
-{
-       struct snd_soc_card *card = &snd_soc_omap_hdmi;
-       int ret;
-
-       card->dev = &pdev->dev;
-
-       ret = snd_soc_register_card(card);
-       if (ret) {
-               dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
-               card->dev = NULL;
-               return ret;
-       }
-       return 0;
-}
-
-static int omap_hdmi_remove(struct platform_device *pdev)
-{
-       struct snd_soc_card *card = platform_get_drvdata(pdev);
-
-       snd_soc_unregister_card(card);
-       card->dev = NULL;
-       return 0;
-}
-
-static struct platform_driver omap_hdmi_driver = {
-       .driver = {
-               .name = DRV_NAME,
-               .owner = THIS_MODULE,
-       },
-       .probe = omap_hdmi_probe,
-       .remove = omap_hdmi_remove,
-};
-
-module_platform_driver(omap_hdmi_driver);
-
-MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
-MODULE_DESCRIPTION("OMAP HDMI machine ASoC driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
deleted file mode 100644 (file)
index eb9c392..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * omap-hdmi.c
- *
- * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
- * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
- *          Ricardo Neri <ricardo.neri@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-#include <sound/asound.h>
-#include <sound/asoundef.h>
-#include <sound/dmaengine_pcm.h>
-#include <video/omapdss.h>
-#include <sound/omap-pcm.h>
-
-#include "omap-hdmi.h"
-
-#define DRV_NAME "omap-hdmi-audio-dai"
-
-struct hdmi_priv {
-       struct snd_dmaengine_dai_dma_data dma_data;
-       unsigned int dma_req;
-       struct omap_dss_audio dss_audio;
-       struct snd_aes_iec958 iec;
-       struct snd_cea_861_aud_if cea;
-       struct omap_dss_device *dssdev;
-};
-
-static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
-                                 struct snd_soc_dai *dai)
-{
-       struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
-       int err;
-       /*
-        * Make sure that the period bytes are multiple of the DMA packet size.
-        * Largest packet size we use is 32 32-bit words = 128 bytes
-        */
-       err = snd_pcm_hw_constraint_step(substream->runtime, 0,
-                                SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
-       if (err < 0) {
-               dev_err(dai->dev, "could not apply constraint\n");
-               return err;
-       }
-
-       if (!priv->dssdev->driver->audio_supported(priv->dssdev)) {
-               dev_err(dai->dev, "audio not supported\n");
-               return -ENODEV;
-       }
-
-       snd_soc_dai_set_dma_data(dai, substream, &priv->dma_data);
-
-       return 0;
-}
-
-static int omap_hdmi_dai_prepare(struct snd_pcm_substream *substream,
-                               struct snd_soc_dai *dai)
-{
-       struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
-
-       return priv->dssdev->driver->audio_enable(priv->dssdev);
-}
-
-static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
-                                   struct snd_pcm_hw_params *params,
-                                   struct snd_soc_dai *dai)
-{
-       struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
-       struct snd_aes_iec958 *iec = &priv->iec;
-       struct snd_cea_861_aud_if *cea = &priv->cea;
-       int err = 0;
-
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
-               priv->dma_data.maxburst = 16;
-               break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-               priv->dma_data.maxburst = 32;
-               break;
-       default:
-               dev_err(dai->dev, "format not supported!\n");
-               return -EINVAL;
-       }
-
-       /*
-        * fill the IEC-60958 channel status word
-        */
-       /* initialize the word bytes */
-       memset(iec->status, 0, sizeof(iec->status));
-
-       /* specify IEC-60958-3 (commercial use) */
-       iec->status[0] &= ~IEC958_AES0_PROFESSIONAL;
-
-       /* specify that the audio is LPCM*/
-       iec->status[0] &= ~IEC958_AES0_NONAUDIO;
-
-       iec->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
-
-       iec->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE;
-
-       iec->status[0] |= IEC958_AES1_PRO_MODE_NOTID;
-
-       iec->status[1] = IEC958_AES1_CON_GENERAL;
-
-       iec->status[2] |= IEC958_AES2_CON_SOURCE_UNSPEC;
-
-       iec->status[2] |= IEC958_AES2_CON_CHANNEL_UNSPEC;
-
-       switch (params_rate(params)) {
-       case 32000:
-               iec->status[3] |= IEC958_AES3_CON_FS_32000;
-               break;
-       case 44100:
-               iec->status[3] |= IEC958_AES3_CON_FS_44100;
-               break;
-       case 48000:
-               iec->status[3] |= IEC958_AES3_CON_FS_48000;
-               break;
-       case 88200:
-               iec->status[3] |= IEC958_AES3_CON_FS_88200;
-               break;
-       case 96000:
-               iec->status[3] |= IEC958_AES3_CON_FS_96000;
-               break;
-       case 176400:
-               iec->status[3] |= IEC958_AES3_CON_FS_176400;
-               break;
-       case 192000:
-               iec->status[3] |= IEC958_AES3_CON_FS_192000;
-               break;
-       default:
-               dev_err(dai->dev, "rate not supported!\n");
-               return -EINVAL;
-       }
-
-       /* specify the clock accuracy */
-       iec->status[3] |= IEC958_AES3_CON_CLOCK_1000PPM;
-
-       /*
-        * specify the word length. The same word length value can mean
-        * two different lengths. Hence, we need to specify the maximum
-        * word length as well.
-        */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
-               iec->status[4] |= IEC958_AES4_CON_WORDLEN_20_16;
-               iec->status[4] &= ~IEC958_AES4_CON_MAX_WORDLEN_24;
-               break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-               iec->status[4] |= IEC958_AES4_CON_WORDLEN_24_20;
-               iec->status[4] |= IEC958_AES4_CON_MAX_WORDLEN_24;
-               break;
-       default:
-               dev_err(dai->dev, "format not supported!\n");
-               return -EINVAL;
-       }
-
-       /*
-        * Fill the CEA-861 audio infoframe (see spec for details)
-        */
-
-       cea->db1_ct_cc = (params_channels(params) - 1)
-               & CEA861_AUDIO_INFOFRAME_DB1CC;
-       cea->db1_ct_cc |= CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM;
-
-       cea->db2_sf_ss = CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM;
-       cea->db2_sf_ss |= CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM;
-
-       cea->db3 = 0; /* not used, all zeros */
-
-       /*
-        * The OMAP HDMI IP requires to use the 8-channel channel code when
-        * transmitting more than two channels.
-        */
-       if (params_channels(params) == 2)
-               cea->db4_ca = 0x0;
-       else
-               cea->db4_ca = 0x13;
-
-       cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED;
-       /* the expression is trivial but makes clear what we are doing */
-       cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV);
-
-       priv->dss_audio.iec = iec;
-       priv->dss_audio.cea = cea;
-
-       err = priv->dssdev->driver->audio_config(priv->dssdev,
-                                                &priv->dss_audio);
-
-       return err;
-}
-
-static int omap_hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
-                               struct snd_soc_dai *dai)
-{
-       struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
-       int err = 0;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               err = priv->dssdev->driver->audio_start(priv->dssdev);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               priv->dssdev->driver->audio_stop(priv->dssdev);
-               break;
-       default:
-               err = -EINVAL;
-       }
-       return err;
-}
-
-static void omap_hdmi_dai_shutdown(struct snd_pcm_substream *substream,
-                               struct snd_soc_dai *dai)
-{
-       struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
-
-       priv->dssdev->driver->audio_disable(priv->dssdev);
-}
-
-static const struct snd_soc_dai_ops omap_hdmi_dai_ops = {
-       .startup        = omap_hdmi_dai_startup,
-       .hw_params      = omap_hdmi_dai_hw_params,
-       .prepare        = omap_hdmi_dai_prepare,
-       .trigger        = omap_hdmi_dai_trigger,
-       .shutdown       = omap_hdmi_dai_shutdown,
-};
-
-static struct snd_soc_dai_driver omap_hdmi_dai = {
-       .playback = {
-               .channels_min = 2,
-               .channels_max = 8,
-               .rates = OMAP_HDMI_RATES,
-               .formats = OMAP_HDMI_FORMATS,
-       },
-       .ops = &omap_hdmi_dai_ops,
-};
-
-static const struct snd_soc_component_driver omap_hdmi_component = {
-       .name           = DRV_NAME,
-};
-
-static int omap_hdmi_probe(struct platform_device *pdev)
-{
-       int ret;
-       struct resource *hdmi_rsrc;
-       struct hdmi_priv *hdmi_data;
-       bool hdmi_dev_found = false;
-
-       hdmi_data = devm_kzalloc(&pdev->dev, sizeof(*hdmi_data), GFP_KERNEL);
-       if (hdmi_data == NULL) {
-               dev_err(&pdev->dev, "Cannot allocate memory for HDMI data\n");
-               return -ENOMEM;
-       }
-
-       hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!hdmi_rsrc) {
-               dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n");
-               return -ENODEV;
-       }
-
-       hdmi_data->dma_data.addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT;
-
-       hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!hdmi_rsrc) {
-               dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n");
-               return -ENODEV;
-       }
-
-       hdmi_data->dma_req = hdmi_rsrc->start;
-       hdmi_data->dma_data.filter_data = &hdmi_data->dma_req;
-       hdmi_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-
-       /*
-        * TODO: We assume that there is only one DSS HDMI device. Future
-        * OMAP implementations may support more than one HDMI devices and
-        * we should provided separate audio support for all of them.
-        */
-       /* Find an HDMI device. */
-       for_each_dss_dev(hdmi_data->dssdev) {
-               omap_dss_get_device(hdmi_data->dssdev);
-
-               if (!hdmi_data->dssdev->driver) {
-                       omap_dss_put_device(hdmi_data->dssdev);
-                       continue;
-               }
-
-               if (hdmi_data->dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
-                       hdmi_dev_found = true;
-                       break;
-               }
-       }
-
-       if (!hdmi_dev_found) {
-               dev_err(&pdev->dev, "no driver for HDMI display found\n");
-               return -ENODEV;
-       }
-
-       dev_set_drvdata(&pdev->dev, hdmi_data);
-       ret = snd_soc_register_component(&pdev->dev, &omap_hdmi_component,
-                                        &omap_hdmi_dai, 1);
-
-       if (ret)
-               return ret;
-
-       return omap_pcm_platform_register(&pdev->dev);
-}
-
-static int omap_hdmi_remove(struct platform_device *pdev)
-{
-       struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev);
-
-       snd_soc_unregister_component(&pdev->dev);
-
-       if (hdmi_data == NULL) {
-               dev_err(&pdev->dev, "cannot obtain HDMi data\n");
-               return -ENODEV;
-       }
-
-       omap_dss_put_device(hdmi_data->dssdev);
-       return 0;
-}
-
-static struct platform_driver hdmi_dai_driver = {
-       .driver = {
-               .name = DRV_NAME,
-               .owner = THIS_MODULE,
-       },
-       .probe = omap_hdmi_probe,
-       .remove = omap_hdmi_remove,
-};
-
-module_platform_driver(hdmi_dai_driver);
-
-MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
-MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
-MODULE_DESCRIPTION("OMAP HDMI SoC Interface");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/omap-hdmi.h b/sound/soc/omap/omap-hdmi.h
deleted file mode 100644 (file)
index 6ad2bf4..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * omap-hdmi.h
- *
- * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
- * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
- *          Ricardo Neri <ricardo.neri@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __OMAP_HDMI_H__
-#define __OMAP_HDMI_H__
-
-#define OMAP_HDMI_AUDIO_DMA_PORT 0x8c
-
-#define OMAP_HDMI_RATES        (SNDRV_PCM_RATE_32000 | \
-                               SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
-                               SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
-                               SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
-
-#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
-                               SNDRV_PCM_FMTBIT_S24_LE)
-
-#endif