From d301a5ac1688bf99039adb10b4516b465f1f7a83 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 25 Oct 2014 11:28:47 -0200 Subject: fbdev: mxsfb: Add support for mx6sl and mx6sx mx6sl and mx6sx share the same LCD controller as mx23 and mx28. Add support for it. The basic difference is the number of clocks that are required: - mx23/mx28: only one clock - mx6sl: two clocks - mx6sx: three clocks Signed-off-by: Fabio Estevam Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index c7bf606..025b439 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -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 diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c index accf48a2..f8ac4a4 100644 --- a/drivers/video/fbdev/mxsfb.c +++ b/drivers/video/fbdev/mxsfb.c @@ -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; -- cgit v0.10.2 From 816764859a5347315cb2f1578cf0252ee129c128 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 1 Nov 2014 01:40:47 +0300 Subject: m501fb: don't return zero on failure path in sm501fb_probe() If no framebuffers found, sm501fb_probe() breaks off initialization, deallocates sm501fb_info, but returns zero. As a result, use after free can happen in sm501fb_remove(). The patch adds -ENODEV as a return value in this case. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index 9e74e8f..8b98b01 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -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; } -- cgit v0.10.2 From 630d2d0de6b113748ce08d5f69e094eeed24accc Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 30 May 2014 16:26:22 +0530 Subject: OMAPDSS: DPI: Use DPI driver data DPI related data is currently a static global struct parameter. It is accessed directly by functions in the driver. This method won't work if we want the driver to support multiple DPI instances. Create struct dpi_data, and pass its pointer to functions which need to use it. We still have a static instance defined for dpi_data, which is accessed by top level DPI ops. This will be removed when the driver dynamically allocates dpi_data for each DPI instance. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c index 4a3363d..35285d8 100644 --- a/drivers/video/fbdev/omap2/dss/dpi.c +++ b/drivers/video/fbdev/omap2/dss/dpi.c @@ -37,7 +37,7 @@ #include "dss.h" #include "dss_features.h" -static struct { +struct dpi_data { struct platform_device *pdev; struct regulator *vdds_dsi_reg; @@ -52,7 +52,9 @@ static struct { struct omap_dss_device output; bool port_initialized; -} dpi; +}; + +static struct dpi_data dpi_data; static struct platform_device *dpi_get_dsidev(enum omap_channel channel) { @@ -200,15 +202,16 @@ 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); + clkin = dsi_get_pll_clkin(dpi->dsidev); memset(ctx, 0, sizeof(*ctx)); - ctx->dsidev = dpi.dsidev; + ctx->dsidev = dpi->dsidev; ctx->pck_min = pck - 1000; ctx->pck_max = pck + 1000; ctx->dsi_cinfo.clkin = clkin; @@ -216,7 +219,7 @@ static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) pll_min = 0; pll_max = 0; - return dsi_pll_calc(dpi.dsidev, clkin, + return dsi_pll_calc(dpi->dsidev, clkin, pll_min, pll_max, dpi_calc_pll_cb, ctx); } @@ -252,7 +255,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,18 +263,18 @@ 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 = dsi_pll_set_clock_div(dpi->dsidev, &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; *lck_div = ctx.dispc_cinfo.lck_div; @@ -280,8 +283,8 @@ static int dpi_set_dsi_clk(enum omap_channel channel, 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 +298,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 +307,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->dsidev) + 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 +340,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_data; + 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 +378,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; } @@ -382,21 +391,21 @@ static int dpi_display_enable(struct omap_dss_device *dssdev) if (r) goto err_src_sel; - if (dpi.dsidev) { - r = dsi_runtime_get(dpi.dsidev); + if (dpi->dsidev) { + r = dsi_runtime_get(dpi->dsidev); if (r) goto err_get_dsi; - r = dsi_pll_init(dpi.dsidev, 0, 1); + r = dsi_pll_init(dpi->dsidev, 0, 1); 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 +413,84 @@ 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->dsidev) + dsi_pll_uninit(dpi->dsidev, true); err_dsi_pll_init: - if (dpi.dsidev) - dsi_runtime_put(dpi.dsidev); + 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_data; + 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->dsidev) { dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); - dsi_pll_uninit(dpi.dsidev, true); - dsi_runtime_put(dpi.dsidev); + dsi_pll_uninit(dpi->dsidev, true); + dsi_runtime_put(dpi->dsidev); } 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_data; + 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_data; + + 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_data; + struct omap_overlay_manager *mgr = dpi->output.manager; int lck_div, pck_div; unsigned long fck; unsigned long pck; @@ -488,8 +503,8 @@ 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->dsidev) { + ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx); if (!ok) return -EINVAL; @@ -514,11 +529,13 @@ 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_data; - 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) @@ -543,36 +560,36 @@ static int dpi_verify_dsi_pll(struct platform_device *dsidev) 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; - if (dpi.dsidev) + if (dpi->dsidev) return; - dsidev = dpi_get_dsidev(dpi.output.dispc_channel); + dsidev = dpi_get_dsidev(dpi->output.dispc_channel); if (!dsidev) return; @@ -581,7 +598,7 @@ static void dpi_init_pll(void) return; } - dpi.dsidev = dsidev; + dpi->dsidev = dsidev; } /* @@ -618,14 +635,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_data; 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,7 +694,8 @@ 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_data; + struct omap_dss_device *out = &dpi->output; out->dev = &pdev->dev; out->id = OMAP_DSS_OUTPUT_DPI; @@ -691,16 +710,21 @@ 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_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_data; + + dpi->pdev = pdev; - mutex_init(&dpi.lock); + dev_set_drvdata(&pdev->dev, dpi); + + mutex_init(&dpi->lock); dpi_init_output(pdev); @@ -736,6 +760,7 @@ void __exit dpi_uninit_platform_driver(void) int __init dpi_init_port(struct platform_device *pdev, struct device_node *port) { + struct dpi_data *dpi = &dpi_data; struct device_node *ep; u32 datalines; int r; @@ -750,17 +775,17 @@ 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; - mutex_init(&dpi.lock); + mutex_init(&dpi->lock); dpi_init_output(pdev); - dpi.port_initialized = true; + dpi->port_initialized = true; return 0; @@ -772,8 +797,10 @@ err_datalines: void __exit dpi_uninit_port(void) { - if (!dpi.port_initialized) + struct dpi_data *dpi = &dpi_data; + + if (!dpi->port_initialized) return; - dpi_uninit_output(dpi.pdev); + dpi_uninit_output(dpi->pdev); } -- cgit v0.10.2 From 2ac6a1aae8f038662b09f2755827dfbe9456894d Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Sun, 1 Jun 2014 12:47:44 +0530 Subject: OMAPDSS: DPI: Allocate driver data Allocate driver data(dpi_data) for each DPI instance. It's allocated in omap_dpi_probe() when DT isn't used, and in dpi_init_port() when DT is used. The dpi_data struct instance is no longer global. In the case of DPI ops, it's retrieved from dpi_get_data_from_dssdev(). 'dssdev' passed by the connected encoder/panel driver is a pointer to the 'output' member in dpi_data, and thus can be used to get the DPI instance's driver data. In the case of probe/ini_port functions, it's set as DPI/DSS device's private data embedded in the platform_device struct. Having dpi_data as private data of the platform device will not work for multiple DPI instances in the DT case. This is because there is no corresponding platform_device for DPI or SDI, they exist only as ports under the parent DSS platform_device in the DT case. The DPI port's private data('data' member in device_node struct) will later be used to store dpi_data. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c index 35285d8..c9face6 100644 --- a/drivers/video/fbdev/omap2/dss/dpi.c +++ b/drivers/video/fbdev/omap2/dss/dpi.c @@ -54,7 +54,15 @@ struct dpi_data { bool port_initialized; }; -static struct dpi_data dpi_data; +static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev) +{ + return container_of(dssdev, struct dpi_data, output); +} + +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) { @@ -359,7 +367,7 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi) static int dpi_display_enable(struct omap_dss_device *dssdev) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); struct omap_dss_device *out = &dpi->output; int r; @@ -439,7 +447,7 @@ err_no_reg: static void dpi_display_disable(struct omap_dss_device *dssdev) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); struct omap_overlay_manager *mgr = dpi->output.manager; mutex_lock(&dpi->lock); @@ -463,7 +471,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev) static void dpi_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); DSSDBG("dpi_set_timings\n"); @@ -477,7 +485,7 @@ static void dpi_set_timings(struct omap_dss_device *dssdev, static void dpi_get_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); mutex_lock(&dpi->lock); @@ -489,7 +497,7 @@ static void dpi_get_timings(struct omap_dss_device *dssdev, static int dpi_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { - struct dpi_data *dpi = &dpi_data; + 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; @@ -529,7 +537,7 @@ static int dpi_check_timings(struct omap_dss_device *dssdev, static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); mutex_lock(&dpi->lock); @@ -635,7 +643,7 @@ 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_data; + struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); struct omap_overlay_manager *mgr; int r; @@ -694,7 +702,7 @@ static const struct omapdss_dpi_ops dpi_ops = { static void dpi_init_output(struct platform_device *pdev) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi = dpi_get_data_from_pdev(pdev); struct omap_dss_device *out = &dpi->output; out->dev = &pdev->dev; @@ -710,7 +718,7 @@ static void dpi_init_output(struct platform_device *pdev) static void __exit dpi_uninit_output(struct platform_device *pdev) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi = dpi_get_data_from_pdev(pdev); struct omap_dss_device *out = &dpi->output; omapdss_unregister_output(out); @@ -718,7 +726,11 @@ static void __exit dpi_uninit_output(struct platform_device *pdev) static int omap_dpi_probe(struct platform_device *pdev) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi; + + dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL); + if (!dpi) + return -ENOMEM; dpi->pdev = pdev; @@ -760,11 +772,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 = &dpi_data; + 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; @@ -787,6 +803,8 @@ int __init dpi_init_port(struct platform_device *pdev, struct device_node *port) dpi->port_initialized = true; + dev_set_drvdata(&pdev->dev, dpi); + return 0; err_datalines: @@ -795,9 +813,9 @@ err_datalines: return r; } -void __exit dpi_uninit_port(void) +void __exit dpi_uninit_port(struct platform_device *pdev) { - struct dpi_data *dpi = &dpi_data; + struct dpi_data *dpi = dpi_get_data_from_pdev(pdev); if (!dpi->port_initialized) return; diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c index 14bcd6c..8a4a6d2 100644 --- a/drivers/video/fbdev/omap2/dss/dss.c +++ b/drivers/video/fbdev/omap2/dss/dss.c @@ -820,10 +820,10 @@ static int __init dss_init_ports(struct platform_device *pdev) 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(); + dpi_uninit_port(pdev); #endif #ifdef CONFIG_OMAP2_DSS_SDI @@ -910,7 +910,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); diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h index 8ff22c1..da7f5f9 100644 --- a/drivers/video/fbdev/omap2/dss/dss.h +++ b/drivers/video/fbdev/omap2/dss/dss.h @@ -359,7 +359,7 @@ int dpi_init_platform_driver(void) __init; void dpi_uninit_platform_driver(void) __exit; int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init; -void dpi_uninit_port(void) __exit; +void dpi_uninit_port(struct platform_device *pdev) __exit; /* DISPC */ int dispc_init_platform_driver(void) __init; -- cgit v0.10.2 From 80eb6751b7cde41cee766230fe07d982d13c1486 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 2 Jun 2014 14:11:51 +0530 Subject: OMAPDSS: DPI: Store dpi_data pointer in the DT port's data DPI and SDI ports are backed by only one parent DSS device. We don't have a corresponding platform_device for ports under DSS. In order to support multiple instances of DPI, we need to pass the driver data pointer through the DPI port's private data ('data' member in device_node struct). dpi_init_output/dpi_uninit_output are untouched and only used for non-DT case, these are called when the DPI platform device probed/removed. These funcs will be removed when non-DT mode is removed. dpi_init_output_port/dpi_uninit_output_port are created and used for the DT path, called when DSS inits/uninits it's ports. These new functions retrieve the dpi_data pointer from 'port->data', and not from the platform device's data(pdev->dev) like in the non-DT path. We add some code in dss_uninit_ports() to pass a pointer to the DPI port in dpi_uninit_port(). Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c index c9face6..224d788 100644 --- a/drivers/video/fbdev/omap2/dss/dpi.c +++ b/drivers/video/fbdev/omap2/dss/dpi.c @@ -59,6 +59,7 @@ 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); @@ -724,6 +725,30 @@ static void __exit dpi_uninit_output(struct platform_device *pdev) 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; + + out->dev = &pdev->dev; + out->id = OMAP_DSS_OUTPUT_DPI; + out->output_type = OMAP_DISPLAY_TYPE_DPI; + out->dispc_channel = dpi_get_channel(); + 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) { struct dpi_data *dpi; @@ -796,15 +821,14 @@ int __init dpi_init_port(struct platform_device *pdev, struct device_node *port) of_node_put(ep); dpi->pdev = pdev; + port->data = dpi; mutex_init(&dpi->lock); - dpi_init_output(pdev); + dpi_init_output_port(pdev, port); dpi->port_initialized = true; - dev_set_drvdata(&pdev->dev, dpi); - return 0; err_datalines: @@ -813,12 +837,12 @@ err_datalines: return r; } -void __exit dpi_uninit_port(struct platform_device *pdev) +void __exit dpi_uninit_port(struct device_node *port) { - struct dpi_data *dpi = dpi_get_data_from_pdev(pdev); + struct dpi_data *dpi = port->data; if (!dpi->port_initialized) return; - dpi_uninit_output(dpi->pdev); + dpi_uninit_output_port(port); } diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c index 8a4a6d2..391a6da 100644 --- a/drivers/video/fbdev/omap2/dss/dss.c +++ b/drivers/video/fbdev/omap2/dss/dss.c @@ -822,8 +822,18 @@ static int __init dss_init_ports(struct platform_device *pdev) static void __exit dss_uninit_ports(struct platform_device *pdev) { + struct device_node *parent = pdev->dev.of_node; + struct device_node *port; + + if (parent == NULL) + return; + + port = omapdss_of_get_next_port(parent, NULL); + if (!port) + return; + #ifdef CONFIG_OMAP2_DSS_DPI - dpi_uninit_port(pdev); + dpi_uninit_port(port); #endif #ifdef CONFIG_OMAP2_DSS_SDI diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h index da7f5f9..5b9db95 100644 --- a/drivers/video/fbdev/omap2/dss/dss.h +++ b/drivers/video/fbdev/omap2/dss/dss.h @@ -359,7 +359,7 @@ int dpi_init_platform_driver(void) __init; void dpi_uninit_platform_driver(void) __exit; int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init; -void dpi_uninit_port(struct platform_device *pdev) __exit; +void dpi_uninit_port(struct device_node *port) __exit; /* DISPC */ int dispc_init_platform_driver(void) __init; -- cgit v0.10.2 From 387ce9f2f2bd78436538deab9ece94512e362deb Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Thu, 22 May 2014 17:01:57 +0530 Subject: OMAPDSS: DSS: init dss ports cleanly The init/uninit port functions are used to set up the DPI and SDI outputs under the dss platform device. A 'reg' property is used to determine the port number of the output. This tells us whether the port is DPI or SDI for OMAP34xx DSS revision. For other DSS revisions, we only have DPI outputs under the dss platform device. For multiple DPI output instances(introduced in DRA7xx DSS), we will use the the port number to specify which DPI output instance is being inited. The current functions work fine if there is only one DPI output instance in DSS. For multiple DPI instances, it would get complicated to figure out whether port number was used to specify whether the output is SDI, or another DPI instance. We create a list of port types supported for each DSS rev, with the index of the port in the list specifying the port number of the output for that DSS revision. This allows us to have a more generic way to init/uninit ports within DSS, and also support multiple DPI ports. We make the uninit_port functions iterative since we will have multiple DPI ports to uninit in the future. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c index 391a6da..7e86b8a 100644 --- a/drivers/video/fbdev/omap2/dss/dss.c +++ b/drivers/video/fbdev/omap2/dss/dss.c @@ -70,6 +70,8 @@ struct dss_features { u8 fck_div_max; u8 dss_fck_multiplier; const char *parent_clk_name; + enum omap_display_type *ports; + int num_ports; int (*dpi_select_source)(enum omap_channel channel); }; @@ -689,6 +691,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 +710,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 +719,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 +728,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 +737,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 +746,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 +755,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,23 +822,32 @@ 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", ®); 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; @@ -832,13 +865,34 @@ static void __exit dss_uninit_ports(struct platform_device *pdev) if (!port) return; -#ifdef CONFIG_OMAP2_DSS_DPI - dpi_uninit_port(port); -#endif + if (dss.feat->num_ports == 0) + return; -#ifdef CONFIG_OMAP2_DSS_SDI - sdi_uninit_port(); -#endif + do { + enum omap_display_type port_type; + u32 reg; + int r; + + r = of_property_read_u32(port, "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 */ diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h index 5b9db95..da4de14 100644 --- a/drivers/video/fbdev/omap2/dss/dss.h +++ b/drivers/video/fbdev/omap2/dss/dss.h @@ -244,8 +244,19 @@ 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 */ @@ -358,8 +369,19 @@ static inline bool dsi_pll_calc(struct platform_device *dsidev, 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(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; diff --git a/drivers/video/fbdev/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/dss/sdi.c index 4c9c46d..d9b10f2 100644 --- a/drivers/video/fbdev/omap2/dss/sdi.c +++ b/drivers/video/fbdev/omap2/dss/sdi.c @@ -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; -- cgit v0.10.2 From ef691ff48bc838e9fca54b58dccac0a7c36a3130 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 22 Apr 2014 17:43:48 +0530 Subject: OMAPDSS: DT: Get source endpoint by matching reg-id In omapdss_of_find_source_for_first_ep, we retrieve a source endpoint's DT node, and then see what omapdss output has the matching device_node pointer in omap_dss_find_output_by_node. For all DPI and SDI outputs, the device_node pointer is set as the parent's DSS device_node pointer. If the source is one of these outputs, the above method won't work. To get the correct output for ports within DSS(and in other cases in the future, where multiple ports might be under one device), we require additional information which is exclusive to the output port. We create a new field in omap_dss_device called 'port_num', this provides port number of the output port corresponding to this device. When searching for the source endpoint in DT, we extract the 'reg' property from the port corresponding to the endpoint source. From the list of registered outputs, we pick out that output which has both dev->of_node and port_num matching with the device_node pointer and 'reg' of the source endpoint node from DT. For encoder blocks(the ones which have both an input and output port), we need to set the port_num as the 'reg' property for the output port as defined in the DT bindings. We set port_num to 1 in the tfp410 and tpd12s015 encoder drivers. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c index 47ee7cd..e349064 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c +++ b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c @@ -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) { diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c index c4abd56..1891967 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c +++ b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c @@ -409,6 +409,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; diff --git a/drivers/video/fbdev/omap2/dss/dss-of.c b/drivers/video/fbdev/omap2/dss/dss-of.c index a4b20aa..928ee63 100644 --- a/drivers/video/fbdev/omap2/dss/dss-of.c +++ b/drivers/video/fbdev/omap2/dss/dss-of.c @@ -20,6 +20,8 @@ #include