diff options
Diffstat (limited to 'drivers/video/fbdev/omap2')
19 files changed, 548 insertions, 247 deletions
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c b/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c index 84a6b3367124..a14d993f719d 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c +++ b/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c | |||
| @@ -201,15 +201,9 @@ static int opa362_probe(struct platform_device *pdev) | |||
| 201 | 201 | ||
| 202 | platform_set_drvdata(pdev, ddata); | 202 | platform_set_drvdata(pdev, ddata); |
| 203 | 203 | ||
| 204 | gpio = devm_gpiod_get(&pdev->dev, "enable"); | 204 | gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW); |
| 205 | if (IS_ERR(gpio)) { | 205 | if (IS_ERR(gpio)) |
| 206 | if (PTR_ERR(gpio) != -ENOENT) | 206 | return PTR_ERR(gpio); |
| 207 | return PTR_ERR(gpio); | ||
| 208 | |||
| 209 | gpio = NULL; | ||
| 210 | } else { | ||
| 211 | gpiod_direction_output(gpio, 0); | ||
| 212 | } | ||
| 213 | 207 | ||
| 214 | ddata->enable_gpio = gpio; | 208 | ddata->enable_gpio = gpio; |
| 215 | 209 | ||
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-dpi.c b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c index eb8fd8140ad0..f7be3489f744 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-dpi.c +++ b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c | |||
| @@ -209,16 +209,9 @@ static int panel_dpi_probe_of(struct platform_device *pdev) | |||
| 209 | struct videomode vm; | 209 | struct videomode vm; |
| 210 | struct gpio_desc *gpio; | 210 | struct gpio_desc *gpio; |
| 211 | 211 | ||
| 212 | gpio = devm_gpiod_get(&pdev->dev, "enable"); | 212 | gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW); |
| 213 | 213 | if (IS_ERR(gpio)) | |
| 214 | if (IS_ERR(gpio)) { | 214 | return PTR_ERR(gpio); |
| 215 | if (PTR_ERR(gpio) != -ENOENT) | ||
| 216 | return PTR_ERR(gpio); | ||
| 217 | else | ||
| 218 | gpio = NULL; | ||
| 219 | } else { | ||
| 220 | gpiod_direction_output(gpio, 0); | ||
| 221 | } | ||
| 222 | 215 | ||
| 223 | ddata->enable_gpio = gpio; | 216 | ddata->enable_gpio = gpio; |
| 224 | 217 | ||
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c index 9974a37a11af..6a1b6a89a928 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c +++ b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c | |||
| @@ -285,15 +285,14 @@ static int lb035q02_probe_of(struct spi_device *spi) | |||
| 285 | struct omap_dss_device *in; | 285 | struct omap_dss_device *in; |
| 286 | struct gpio_desc *gpio; | 286 | struct gpio_desc *gpio; |
| 287 | 287 | ||
| 288 | gpio = devm_gpiod_get(&spi->dev, "enable"); | 288 | gpio = devm_gpiod_get(&spi->dev, "enable", GPIOD_OUT_LOW); |
| 289 | if (IS_ERR(gpio)) { | 289 | if (IS_ERR(gpio)) { |
| 290 | dev_err(&spi->dev, "failed to parse enable gpio\n"); | 290 | dev_err(&spi->dev, "failed to parse enable gpio\n"); |
| 291 | return PTR_ERR(gpio); | 291 | return PTR_ERR(gpio); |
| 292 | } else { | ||
| 293 | gpiod_direction_output(gpio, 0); | ||
| 294 | ddata->enable_gpio = gpio; | ||
| 295 | } | 292 | } |
| 296 | 293 | ||
| 294 | ddata->enable_gpio = gpio; | ||
| 295 | |||
| 297 | ddata->backlight_gpio = -ENOENT; | 296 | ddata->backlight_gpio = -ENOENT; |
| 298 | 297 | ||
| 299 | in = omapdss_of_find_source_for_first_ep(node); | 298 | in = omapdss_of_find_source_for_first_ep(node); |
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c index eae263702964..abfd1f6e3327 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c +++ b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c | |||
| @@ -268,17 +268,12 @@ static int sharp_ls_get_gpio_of(struct device *dev, int index, int val, | |||
| 268 | const char *desc, struct gpio_desc **gpiod) | 268 | const char *desc, struct gpio_desc **gpiod) |
| 269 | { | 269 | { |
| 270 | struct gpio_desc *gd; | 270 | struct gpio_desc *gd; |
| 271 | int r; | ||
| 272 | 271 | ||
| 273 | *gpiod = NULL; | 272 | *gpiod = NULL; |
| 274 | 273 | ||
| 275 | gd = devm_gpiod_get_index(dev, desc, index); | 274 | gd = devm_gpiod_get_index(dev, desc, index, GPIOD_OUT_LOW); |
| 276 | if (IS_ERR(gd)) | 275 | if (IS_ERR(gd)) |
| 277 | return PTR_ERR(gd) == -ENOENT ? 0 : PTR_ERR(gd); | 276 | return PTR_ERR(gd); |
| 278 | |||
| 279 | r = gpiod_direction_output(gd, val); | ||
| 280 | if (r) | ||
| 281 | return r; | ||
| 282 | 277 | ||
| 283 | *gpiod = gd; | 278 | *gpiod = gd; |
| 284 | return 0; | 279 | return 0; |
diff --git a/drivers/video/fbdev/omap2/dss/core.c b/drivers/video/fbdev/omap2/dss/core.c index 16751755d433..54eeb507f9b3 100644 --- a/drivers/video/fbdev/omap2/dss/core.c +++ b/drivers/video/fbdev/omap2/dss/core.c | |||
| @@ -50,8 +50,6 @@ static char *def_disp_name; | |||
| 50 | module_param_named(def_disp, def_disp_name, charp, 0); | 50 | module_param_named(def_disp, def_disp_name, charp, 0); |
| 51 | MODULE_PARM_DESC(def_disp, "default display name"); | 51 | MODULE_PARM_DESC(def_disp, "default display name"); |
| 52 | 52 | ||
| 53 | static bool dss_initialized; | ||
| 54 | |||
| 55 | const char *omapdss_get_default_display_name(void) | 53 | const char *omapdss_get_default_display_name(void) |
| 56 | { | 54 | { |
| 57 | return core.default_display_name; | 55 | return core.default_display_name; |
| @@ -65,12 +63,6 @@ enum omapdss_version omapdss_get_version(void) | |||
| 65 | } | 63 | } |
| 66 | EXPORT_SYMBOL(omapdss_get_version); | 64 | EXPORT_SYMBOL(omapdss_get_version); |
| 67 | 65 | ||
| 68 | bool omapdss_is_initialized(void) | ||
| 69 | { | ||
| 70 | return dss_initialized; | ||
| 71 | } | ||
| 72 | EXPORT_SYMBOL(omapdss_is_initialized); | ||
| 73 | |||
| 74 | struct platform_device *dss_get_core_pdev(void) | 66 | struct platform_device *dss_get_core_pdev(void) |
| 75 | { | 67 | { |
| 76 | return core.pdev; | 68 | return core.pdev; |
| @@ -253,6 +245,8 @@ static struct platform_driver omap_dss_driver = { | |||
| 253 | 245 | ||
| 254 | /* INIT */ | 246 | /* INIT */ |
| 255 | static int (*dss_output_drv_reg_funcs[])(void) __initdata = { | 247 | static int (*dss_output_drv_reg_funcs[])(void) __initdata = { |
| 248 | dss_init_platform_driver, | ||
| 249 | dispc_init_platform_driver, | ||
| 256 | #ifdef CONFIG_OMAP2_DSS_DSI | 250 | #ifdef CONFIG_OMAP2_DSS_DSI |
| 257 | dsi_init_platform_driver, | 251 | dsi_init_platform_driver, |
| 258 | #endif | 252 | #endif |
| @@ -276,32 +270,32 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = { | |||
| 276 | #endif | 270 | #endif |
| 277 | }; | 271 | }; |
| 278 | 272 | ||
| 279 | static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = { | 273 | static void (*dss_output_drv_unreg_funcs[])(void) = { |
| 280 | #ifdef CONFIG_OMAP2_DSS_DSI | 274 | #ifdef CONFIG_OMAP5_DSS_HDMI |
| 281 | dsi_uninit_platform_driver, | 275 | hdmi5_uninit_platform_driver, |
| 282 | #endif | 276 | #endif |
| 283 | #ifdef CONFIG_OMAP2_DSS_DPI | 277 | #ifdef CONFIG_OMAP4_DSS_HDMI |
| 284 | dpi_uninit_platform_driver, | 278 | hdmi4_uninit_platform_driver, |
| 285 | #endif | 279 | #endif |
| 286 | #ifdef CONFIG_OMAP2_DSS_SDI | 280 | #ifdef CONFIG_OMAP2_DSS_VENC |
| 287 | sdi_uninit_platform_driver, | 281 | venc_uninit_platform_driver, |
| 288 | #endif | 282 | #endif |
| 289 | #ifdef CONFIG_OMAP2_DSS_RFBI | 283 | #ifdef CONFIG_OMAP2_DSS_RFBI |
| 290 | rfbi_uninit_platform_driver, | 284 | rfbi_uninit_platform_driver, |
| 291 | #endif | 285 | #endif |
| 292 | #ifdef CONFIG_OMAP2_DSS_VENC | 286 | #ifdef CONFIG_OMAP2_DSS_SDI |
| 293 | venc_uninit_platform_driver, | 287 | sdi_uninit_platform_driver, |
| 294 | #endif | 288 | #endif |
| 295 | #ifdef CONFIG_OMAP4_DSS_HDMI | 289 | #ifdef CONFIG_OMAP2_DSS_DPI |
| 296 | hdmi4_uninit_platform_driver, | 290 | dpi_uninit_platform_driver, |
| 297 | #endif | 291 | #endif |
| 298 | #ifdef CONFIG_OMAP5_DSS_HDMI | 292 | #ifdef CONFIG_OMAP2_DSS_DSI |
| 299 | hdmi5_uninit_platform_driver, | 293 | dsi_uninit_platform_driver, |
| 300 | #endif | 294 | #endif |
| 295 | dispc_uninit_platform_driver, | ||
| 296 | dss_uninit_platform_driver, | ||
| 301 | }; | 297 | }; |
| 302 | 298 | ||
| 303 | static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)]; | ||
| 304 | |||
| 305 | static int __init omap_dss_init(void) | 299 | static int __init omap_dss_init(void) |
| 306 | { | 300 | { |
| 307 | int r; | 301 | int r; |
| @@ -311,35 +305,20 @@ static int __init omap_dss_init(void) | |||
| 311 | if (r) | 305 | if (r) |
| 312 | return r; | 306 | return r; |
| 313 | 307 | ||
| 314 | r = dss_init_platform_driver(); | ||
| 315 | if (r) { | ||
| 316 | DSSERR("Failed to initialize DSS platform driver\n"); | ||
| 317 | goto err_dss; | ||
| 318 | } | ||
| 319 | |||
| 320 | r = dispc_init_platform_driver(); | ||
| 321 | if (r) { | ||
| 322 | DSSERR("Failed to initialize dispc platform driver\n"); | ||
| 323 | goto err_dispc; | ||
| 324 | } | ||
| 325 | |||
| 326 | /* | ||
| 327 | * It's ok if the output-driver register fails. It happens, for example, | ||
| 328 | * when there is no output-device (e.g. SDI for OMAP4). | ||
| 329 | */ | ||
| 330 | for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) { | 308 | for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) { |
| 331 | r = dss_output_drv_reg_funcs[i](); | 309 | r = dss_output_drv_reg_funcs[i](); |
| 332 | if (r == 0) | 310 | if (r) |
| 333 | dss_output_drv_loaded[i] = true; | 311 | goto err_reg; |
| 334 | } | 312 | } |
| 335 | 313 | ||
| 336 | dss_initialized = true; | ||
| 337 | |||
| 338 | return 0; | 314 | return 0; |
| 339 | 315 | ||
| 340 | err_dispc: | 316 | err_reg: |
| 341 | dss_uninit_platform_driver(); | 317 | for (i = ARRAY_SIZE(dss_output_drv_reg_funcs) - i; |
| 342 | err_dss: | 318 | i < ARRAY_SIZE(dss_output_drv_reg_funcs); |
| 319 | ++i) | ||
| 320 | dss_output_drv_unreg_funcs[i](); | ||
| 321 | |||
| 343 | platform_driver_unregister(&omap_dss_driver); | 322 | platform_driver_unregister(&omap_dss_driver); |
| 344 | 323 | ||
| 345 | return r; | 324 | return r; |
| @@ -349,13 +328,8 @@ static void __exit omap_dss_exit(void) | |||
| 349 | { | 328 | { |
| 350 | int i; | 329 | int i; |
| 351 | 330 | ||
| 352 | for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) { | 331 | for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) |
| 353 | if (dss_output_drv_loaded[i]) | 332 | dss_output_drv_unreg_funcs[i](); |
| 354 | dss_output_drv_unreg_funcs[i](); | ||
| 355 | } | ||
| 356 | |||
| 357 | dispc_uninit_platform_driver(); | ||
| 358 | dss_uninit_platform_driver(); | ||
| 359 | 333 | ||
| 360 | platform_driver_unregister(&omap_dss_driver); | 334 | platform_driver_unregister(&omap_dss_driver); |
| 361 | } | 335 | } |
diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index f4fc77d9d3bf..be716c9ffb88 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/mfd/syscon.h> | 39 | #include <linux/mfd/syscon.h> |
| 40 | #include <linux/regmap.h> | 40 | #include <linux/regmap.h> |
| 41 | #include <linux/of.h> | 41 | #include <linux/of.h> |
| 42 | #include <linux/component.h> | ||
| 42 | 43 | ||
| 43 | #include <video/omapdss.h> | 44 | #include <video/omapdss.h> |
| 44 | 45 | ||
| @@ -95,6 +96,9 @@ struct dispc_features { | |||
| 95 | bool mstandby_workaround:1; | 96 | bool mstandby_workaround:1; |
| 96 | 97 | ||
| 97 | bool set_max_preload:1; | 98 | bool set_max_preload:1; |
| 99 | |||
| 100 | /* PIXEL_INC is not added to the last pixel of a line */ | ||
| 101 | bool last_pixel_inc_missing:1; | ||
| 98 | }; | 102 | }; |
| 99 | 103 | ||
| 100 | #define DISPC_MAX_NR_FIFOS 5 | 104 | #define DISPC_MAX_NR_FIFOS 5 |
| @@ -1741,6 +1745,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, | |||
| 1741 | row_repeat = false; | 1745 | row_repeat = false; |
| 1742 | } | 1746 | } |
| 1743 | 1747 | ||
| 1748 | /* | ||
| 1749 | * OMAP4/5 Errata i631: | ||
| 1750 | * NV12 in 1D mode must use ROTATION=1. Otherwise DSS will fetch extra | ||
| 1751 | * rows beyond the framebuffer, which may cause OCP error. | ||
| 1752 | */ | ||
| 1753 | if (color_mode == OMAP_DSS_COLOR_NV12 && | ||
| 1754 | rotation_type != OMAP_DSS_ROT_TILER) | ||
| 1755 | vidrot = 1; | ||
| 1756 | |||
| 1744 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); | 1757 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); |
| 1745 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) | 1758 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) |
| 1746 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), | 1759 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), |
| @@ -2154,7 +2167,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, | |||
| 2154 | if (height > out_height) { | 2167 | if (height > out_height) { |
| 2155 | unsigned int ppl = mgr_timings->x_res; | 2168 | unsigned int ppl = mgr_timings->x_res; |
| 2156 | 2169 | ||
| 2157 | tmp = pclk * height * out_width; | 2170 | tmp = (u64)pclk * height * out_width; |
| 2158 | do_div(tmp, 2 * out_height * ppl); | 2171 | do_div(tmp, 2 * out_height * ppl); |
| 2159 | core_clk = tmp; | 2172 | core_clk = tmp; |
| 2160 | 2173 | ||
| @@ -2162,14 +2175,14 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, | |||
| 2162 | if (ppl == out_width) | 2175 | if (ppl == out_width) |
| 2163 | return 0; | 2176 | return 0; |
| 2164 | 2177 | ||
| 2165 | tmp = pclk * (height - 2 * out_height) * out_width; | 2178 | tmp = (u64)pclk * (height - 2 * out_height) * out_width; |
| 2166 | do_div(tmp, 2 * out_height * (ppl - out_width)); | 2179 | do_div(tmp, 2 * out_height * (ppl - out_width)); |
| 2167 | core_clk = max_t(u32, core_clk, tmp); | 2180 | core_clk = max_t(u32, core_clk, tmp); |
| 2168 | } | 2181 | } |
| 2169 | } | 2182 | } |
| 2170 | 2183 | ||
| 2171 | if (width > out_width) { | 2184 | if (width > out_width) { |
| 2172 | tmp = pclk * width; | 2185 | tmp = (u64)pclk * width; |
| 2173 | do_div(tmp, out_width); | 2186 | do_div(tmp, out_width); |
| 2174 | core_clk = max_t(u32, core_clk, tmp); | 2187 | core_clk = max_t(u32, core_clk, tmp); |
| 2175 | 2188 | ||
| @@ -2267,6 +2280,11 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, | |||
| 2267 | } | 2280 | } |
| 2268 | } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); | 2281 | } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); |
| 2269 | 2282 | ||
| 2283 | if (error) { | ||
| 2284 | DSSERR("failed to find scaling settings\n"); | ||
| 2285 | return -EINVAL; | ||
| 2286 | } | ||
| 2287 | |||
| 2270 | if (in_width > maxsinglelinewidth) { | 2288 | if (in_width > maxsinglelinewidth) { |
| 2271 | DSSERR("Cannot scale max input width exceeded"); | 2289 | DSSERR("Cannot scale max input width exceeded"); |
| 2272 | return -EINVAL; | 2290 | return -EINVAL; |
| @@ -2283,7 +2301,6 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, | |||
| 2283 | { | 2301 | { |
| 2284 | int error; | 2302 | int error; |
| 2285 | u16 in_width, in_height; | 2303 | u16 in_width, in_height; |
| 2286 | int min_factor = min(*decim_x, *decim_y); | ||
| 2287 | const int maxsinglelinewidth = | 2304 | const int maxsinglelinewidth = |
| 2288 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | 2305 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); |
| 2289 | 2306 | ||
| @@ -2317,20 +2334,32 @@ again: | |||
| 2317 | error = (error || in_width > maxsinglelinewidth * 2 || | 2334 | error = (error || in_width > maxsinglelinewidth * 2 || |
| 2318 | (in_width > maxsinglelinewidth && *five_taps) || | 2335 | (in_width > maxsinglelinewidth && *five_taps) || |
| 2319 | !*core_clk || *core_clk > dispc_core_clk_rate()); | 2336 | !*core_clk || *core_clk > dispc_core_clk_rate()); |
| 2320 | if (error) { | 2337 | |
| 2321 | if (*decim_x == *decim_y) { | 2338 | if (!error) { |
| 2322 | *decim_x = min_factor; | 2339 | /* verify that we're inside the limits of scaler */ |
| 2323 | ++*decim_y; | 2340 | if (in_width / 4 > out_width) |
| 2341 | error = 1; | ||
| 2342 | |||
| 2343 | if (*five_taps) { | ||
| 2344 | if (in_height / 4 > out_height) | ||
| 2345 | error = 1; | ||
| 2324 | } else { | 2346 | } else { |
| 2325 | swap(*decim_x, *decim_y); | 2347 | if (in_height / 2 > out_height) |
| 2326 | if (*decim_x < *decim_y) | 2348 | error = 1; |
| 2327 | ++*decim_x; | ||
| 2328 | } | 2349 | } |
| 2329 | } | 2350 | } |
| 2351 | |||
| 2352 | if (error) | ||
| 2353 | ++*decim_y; | ||
| 2330 | } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); | 2354 | } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); |
| 2331 | 2355 | ||
| 2332 | if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width, | 2356 | if (error) { |
| 2333 | height, out_width, out_height, *five_taps)) { | 2357 | DSSERR("failed to find scaling settings\n"); |
| 2358 | return -EINVAL; | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width, | ||
| 2362 | in_height, out_width, out_height, *five_taps)) { | ||
| 2334 | DSSERR("horizontal timing too tight\n"); | 2363 | DSSERR("horizontal timing too tight\n"); |
| 2335 | return -EINVAL; | 2364 | return -EINVAL; |
| 2336 | } | 2365 | } |
| @@ -2390,6 +2419,9 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, | |||
| 2390 | return 0; | 2419 | return 0; |
| 2391 | } | 2420 | } |
| 2392 | 2421 | ||
| 2422 | #define DIV_FRAC(dividend, divisor) \ | ||
| 2423 | ((dividend) * 100 / (divisor) - ((dividend) / (divisor) * 100)) | ||
| 2424 | |||
| 2393 | static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, | 2425 | static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, |
| 2394 | enum omap_overlay_caps caps, | 2426 | enum omap_overlay_caps caps, |
| 2395 | const struct omap_video_timings *mgr_timings, | 2427 | const struct omap_video_timings *mgr_timings, |
| @@ -2449,8 +2481,19 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, | |||
| 2449 | if (ret) | 2481 | if (ret) |
| 2450 | return ret; | 2482 | return ret; |
| 2451 | 2483 | ||
| 2452 | DSSDBG("required core clk rate = %lu Hz\n", core_clk); | 2484 | DSSDBG("%dx%d -> %dx%d (%d.%02d x %d.%02d), decim %dx%d %dx%d (%d.%02d x %d.%02d), taps %d, req clk %lu, cur clk %lu\n", |
| 2453 | DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); | 2485 | width, height, |
| 2486 | out_width, out_height, | ||
| 2487 | out_width / width, DIV_FRAC(out_width, width), | ||
| 2488 | out_height / height, DIV_FRAC(out_height, height), | ||
| 2489 | |||
| 2490 | decim_x, decim_y, | ||
| 2491 | width / decim_x, height / decim_y, | ||
| 2492 | out_width / (width / decim_x), DIV_FRAC(out_width, width / decim_x), | ||
| 2493 | out_height / (height / decim_y), DIV_FRAC(out_height, height / decim_y), | ||
| 2494 | |||
| 2495 | *five_taps ? 5 : 3, | ||
| 2496 | core_clk, dispc_core_clk_rate()); | ||
| 2454 | 2497 | ||
| 2455 | if (!core_clk || core_clk > dispc_core_clk_rate()) { | 2498 | if (!core_clk || core_clk > dispc_core_clk_rate()) { |
| 2456 | DSSERR("failed to set up scaling, " | 2499 | DSSERR("failed to set up scaling, " |
| @@ -2533,6 +2576,21 @@ static int dispc_ovl_setup_common(enum omap_plane plane, | |||
| 2533 | if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER) | 2576 | if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER) |
| 2534 | return -EINVAL; | 2577 | return -EINVAL; |
| 2535 | 2578 | ||
| 2579 | switch (color_mode) { | ||
| 2580 | case OMAP_DSS_COLOR_YUV2: | ||
| 2581 | case OMAP_DSS_COLOR_UYVY: | ||
| 2582 | case OMAP_DSS_COLOR_NV12: | ||
| 2583 | if (in_width & 1) { | ||
| 2584 | DSSERR("input width %d is not even for YUV format\n", | ||
| 2585 | in_width); | ||
| 2586 | return -EINVAL; | ||
| 2587 | } | ||
| 2588 | break; | ||
| 2589 | |||
| 2590 | default: | ||
| 2591 | break; | ||
| 2592 | } | ||
| 2593 | |||
| 2536 | out_width = out_width == 0 ? width : out_width; | 2594 | out_width = out_width == 0 ? width : out_width; |
| 2537 | out_height = out_height == 0 ? height : out_height; | 2595 | out_height = out_height == 0 ? height : out_height; |
| 2538 | 2596 | ||
| @@ -2563,6 +2621,27 @@ static int dispc_ovl_setup_common(enum omap_plane plane, | |||
| 2563 | in_width = in_width / x_predecim; | 2621 | in_width = in_width / x_predecim; |
| 2564 | in_height = in_height / y_predecim; | 2622 | in_height = in_height / y_predecim; |
| 2565 | 2623 | ||
| 2624 | if (x_predecim > 1 || y_predecim > 1) | ||
| 2625 | DSSDBG("predecimation %d x %x, new input size %d x %d\n", | ||
| 2626 | x_predecim, y_predecim, in_width, in_height); | ||
| 2627 | |||
| 2628 | switch (color_mode) { | ||
| 2629 | case OMAP_DSS_COLOR_YUV2: | ||
| 2630 | case OMAP_DSS_COLOR_UYVY: | ||
| 2631 | case OMAP_DSS_COLOR_NV12: | ||
| 2632 | if (in_width & 1) { | ||
| 2633 | DSSDBG("predecimated input width is not even for YUV format\n"); | ||
| 2634 | DSSDBG("adjusting input width %d -> %d\n", | ||
| 2635 | in_width, in_width & ~1); | ||
| 2636 | |||
| 2637 | in_width &= ~1; | ||
| 2638 | } | ||
| 2639 | break; | ||
| 2640 | |||
| 2641 | default: | ||
| 2642 | break; | ||
| 2643 | } | ||
| 2644 | |||
| 2566 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | 2645 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
| 2567 | color_mode == OMAP_DSS_COLOR_UYVY || | 2646 | color_mode == OMAP_DSS_COLOR_UYVY || |
| 2568 | color_mode == OMAP_DSS_COLOR_NV12) | 2647 | color_mode == OMAP_DSS_COLOR_NV12) |
| @@ -2632,6 +2711,9 @@ static int dispc_ovl_setup_common(enum omap_plane plane, | |||
| 2632 | dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1); | 2711 | dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1); |
| 2633 | } | 2712 | } |
| 2634 | 2713 | ||
| 2714 | if (dispc.feat->last_pixel_inc_missing) | ||
| 2715 | row_inc += pix_inc - 1; | ||
| 2716 | |||
| 2635 | dispc_ovl_set_row_inc(plane, row_inc); | 2717 | dispc_ovl_set_row_inc(plane, row_inc); |
| 2636 | dispc_ovl_set_pix_inc(plane, pix_inc); | 2718 | dispc_ovl_set_pix_inc(plane, pix_inc); |
| 2637 | 2719 | ||
| @@ -3692,7 +3774,7 @@ static void _omap_dispc_initial_config(void) | |||
| 3692 | dispc_init_mflag(); | 3774 | dispc_init_mflag(); |
| 3693 | } | 3775 | } |
| 3694 | 3776 | ||
| 3695 | static const struct dispc_features omap24xx_dispc_feats __initconst = { | 3777 | static const struct dispc_features omap24xx_dispc_feats = { |
| 3696 | .sw_start = 5, | 3778 | .sw_start = 5, |
| 3697 | .fp_start = 15, | 3779 | .fp_start = 15, |
| 3698 | .bp_start = 27, | 3780 | .bp_start = 27, |
| @@ -3709,9 +3791,10 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = { | |||
| 3709 | .num_fifos = 3, | 3791 | .num_fifos = 3, |
| 3710 | .no_framedone_tv = true, | 3792 | .no_framedone_tv = true, |
| 3711 | .set_max_preload = false, | 3793 | .set_max_preload = false, |
| 3794 | .last_pixel_inc_missing = true, | ||
| 3712 | }; | 3795 | }; |
| 3713 | 3796 | ||
| 3714 | static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { | 3797 | static const struct dispc_features omap34xx_rev1_0_dispc_feats = { |
| 3715 | .sw_start = 5, | 3798 | .sw_start = 5, |
| 3716 | .fp_start = 15, | 3799 | .fp_start = 15, |
| 3717 | .bp_start = 27, | 3800 | .bp_start = 27, |
| @@ -3729,9 +3812,10 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { | |||
| 3729 | .num_fifos = 3, | 3812 | .num_fifos = 3, |
| 3730 | .no_framedone_tv = true, | 3813 | .no_framedone_tv = true, |
| 3731 | .set_max_preload = false, | 3814 | .set_max_preload = false, |
| 3815 | .last_pixel_inc_missing = true, | ||
| 3732 | }; | 3816 | }; |
| 3733 | 3817 | ||
| 3734 | static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { | 3818 | static const struct dispc_features omap34xx_rev3_0_dispc_feats = { |
| 3735 | .sw_start = 7, | 3819 | .sw_start = 7, |
| 3736 | .fp_start = 19, | 3820 | .fp_start = 19, |
| 3737 | .bp_start = 31, | 3821 | .bp_start = 31, |
| @@ -3749,9 +3833,10 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { | |||
| 3749 | .num_fifos = 3, | 3833 | .num_fifos = 3, |
| 3750 | .no_framedone_tv = true, | 3834 | .no_framedone_tv = true, |
| 3751 | .set_max_preload = false, | 3835 | .set_max_preload = false, |
| 3836 | .last_pixel_inc_missing = true, | ||
| 3752 | }; | 3837 | }; |
| 3753 | 3838 | ||
| 3754 | static const struct dispc_features omap44xx_dispc_feats __initconst = { | 3839 | static const struct dispc_features omap44xx_dispc_feats = { |
| 3755 | .sw_start = 7, | 3840 | .sw_start = 7, |
| 3756 | .fp_start = 19, | 3841 | .fp_start = 19, |
| 3757 | .bp_start = 31, | 3842 | .bp_start = 31, |
| @@ -3771,7 +3856,7 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = { | |||
| 3771 | .set_max_preload = true, | 3856 | .set_max_preload = true, |
| 3772 | }; | 3857 | }; |
| 3773 | 3858 | ||
| 3774 | static const struct dispc_features omap54xx_dispc_feats __initconst = { | 3859 | static const struct dispc_features omap54xx_dispc_feats = { |
| 3775 | .sw_start = 7, | 3860 | .sw_start = 7, |
| 3776 | .fp_start = 19, | 3861 | .fp_start = 19, |
| 3777 | .bp_start = 31, | 3862 | .bp_start = 31, |
| @@ -3792,7 +3877,7 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = { | |||
| 3792 | .set_max_preload = true, | 3877 | .set_max_preload = true, |
| 3793 | }; | 3878 | }; |
| 3794 | 3879 | ||
| 3795 | static int __init dispc_init_features(struct platform_device *pdev) | 3880 | static int dispc_init_features(struct platform_device *pdev) |
| 3796 | { | 3881 | { |
| 3797 | const struct dispc_features *src; | 3882 | const struct dispc_features *src; |
| 3798 | struct dispc_features *dst; | 3883 | struct dispc_features *dst; |
| @@ -3882,8 +3967,9 @@ void dispc_free_irq(void *dev_id) | |||
| 3882 | EXPORT_SYMBOL(dispc_free_irq); | 3967 | EXPORT_SYMBOL(dispc_free_irq); |
| 3883 | 3968 | ||
| 3884 | /* DISPC HW IP initialisation */ | 3969 | /* DISPC HW IP initialisation */ |
| 3885 | static int __init omap_dispchw_probe(struct platform_device *pdev) | 3970 | static int dispc_bind(struct device *dev, struct device *master, void *data) |
| 3886 | { | 3971 | { |
| 3972 | struct platform_device *pdev = to_platform_device(dev); | ||
| 3887 | u32 rev; | 3973 | u32 rev; |
| 3888 | int r = 0; | 3974 | int r = 0; |
| 3889 | struct resource *dispc_mem; | 3975 | struct resource *dispc_mem; |
| @@ -3955,12 +4041,27 @@ err_runtime_get: | |||
| 3955 | return r; | 4041 | return r; |
| 3956 | } | 4042 | } |
| 3957 | 4043 | ||
| 3958 | static int __exit omap_dispchw_remove(struct platform_device *pdev) | 4044 | static void dispc_unbind(struct device *dev, struct device *master, |
| 4045 | void *data) | ||
| 3959 | { | 4046 | { |
| 3960 | pm_runtime_disable(&pdev->dev); | 4047 | pm_runtime_disable(dev); |
| 3961 | 4048 | ||
| 3962 | dss_uninit_overlay_managers(); | 4049 | dss_uninit_overlay_managers(); |
| 4050 | } | ||
| 4051 | |||
| 4052 | static const struct component_ops dispc_component_ops = { | ||
| 4053 | .bind = dispc_bind, | ||
| 4054 | .unbind = dispc_unbind, | ||
| 4055 | }; | ||
| 3963 | 4056 | ||
| 4057 | static int dispc_probe(struct platform_device *pdev) | ||
| 4058 | { | ||
| 4059 | return component_add(&pdev->dev, &dispc_component_ops); | ||
| 4060 | } | ||
| 4061 | |||
| 4062 | static int dispc_remove(struct platform_device *pdev) | ||
| 4063 | { | ||
| 4064 | component_del(&pdev->dev, &dispc_component_ops); | ||
| 3964 | return 0; | 4065 | return 0; |
| 3965 | } | 4066 | } |
| 3966 | 4067 | ||
| @@ -4013,7 +4114,8 @@ static const struct of_device_id dispc_of_match[] = { | |||
| 4013 | }; | 4114 | }; |
| 4014 | 4115 | ||
| 4015 | static struct platform_driver omap_dispchw_driver = { | 4116 | static struct platform_driver omap_dispchw_driver = { |
| 4016 | .remove = __exit_p(omap_dispchw_remove), | 4117 | .probe = dispc_probe, |
| 4118 | .remove = dispc_remove, | ||
| 4017 | .driver = { | 4119 | .driver = { |
| 4018 | .name = "omapdss_dispc", | 4120 | .name = "omapdss_dispc", |
| 4019 | .pm = &dispc_pm_ops, | 4121 | .pm = &dispc_pm_ops, |
| @@ -4024,10 +4126,10 @@ static struct platform_driver omap_dispchw_driver = { | |||
| 4024 | 4126 | ||
| 4025 | int __init dispc_init_platform_driver(void) | 4127 | int __init dispc_init_platform_driver(void) |
| 4026 | { | 4128 | { |
| 4027 | return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe); | 4129 | return platform_driver_register(&omap_dispchw_driver); |
| 4028 | } | 4130 | } |
| 4029 | 4131 | ||
| 4030 | void __exit dispc_uninit_platform_driver(void) | 4132 | void dispc_uninit_platform_driver(void) |
| 4031 | { | 4133 | { |
| 4032 | platform_driver_unregister(&omap_dispchw_driver); | 4134 | platform_driver_unregister(&omap_dispchw_driver); |
| 4033 | } | 4135 | } |
diff --git a/drivers/video/fbdev/omap2/dss/display-sysfs.c b/drivers/video/fbdev/omap2/dss/display-sysfs.c index 12186557a9d4..6ad0991f8259 100644 --- a/drivers/video/fbdev/omap2/dss/display-sysfs.c +++ b/drivers/video/fbdev/omap2/dss/display-sysfs.c | |||
| @@ -324,7 +324,7 @@ int display_init_sysfs(struct platform_device *pdev) | |||
| 324 | 324 | ||
| 325 | for_each_dss_dev(dssdev) { | 325 | for_each_dss_dev(dssdev) { |
| 326 | r = kobject_init_and_add(&dssdev->kobj, &display_ktype, | 326 | r = kobject_init_and_add(&dssdev->kobj, &display_ktype, |
| 327 | &pdev->dev.kobj, dssdev->alias); | 327 | &pdev->dev.kobj, "%s", dssdev->alias); |
| 328 | if (r) { | 328 | if (r) { |
| 329 | DSSERR("failed to create sysfs files\n"); | 329 | DSSERR("failed to create sysfs files\n"); |
| 330 | omap_dss_put_device(dssdev); | 330 | omap_dss_put_device(dssdev); |
diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c index f83e7b030249..fb45b6432968 100644 --- a/drivers/video/fbdev/omap2/dss/dpi.c +++ b/drivers/video/fbdev/omap2/dss/dpi.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/string.h> | 32 | #include <linux/string.h> |
| 33 | #include <linux/of.h> | 33 | #include <linux/of.h> |
| 34 | #include <linux/clk.h> | 34 | #include <linux/clk.h> |
| 35 | #include <linux/component.h> | ||
| 35 | 36 | ||
| 36 | #include <video/omapdss.h> | 37 | #include <video/omapdss.h> |
| 37 | 38 | ||
| @@ -731,7 +732,7 @@ static void dpi_init_output(struct platform_device *pdev) | |||
| 731 | omapdss_register_output(out); | 732 | omapdss_register_output(out); |
| 732 | } | 733 | } |
| 733 | 734 | ||
| 734 | static void __exit dpi_uninit_output(struct platform_device *pdev) | 735 | static void dpi_uninit_output(struct platform_device *pdev) |
| 735 | { | 736 | { |
| 736 | struct dpi_data *dpi = dpi_get_data_from_pdev(pdev); | 737 | struct dpi_data *dpi = dpi_get_data_from_pdev(pdev); |
| 737 | struct omap_dss_device *out = &dpi->output; | 738 | struct omap_dss_device *out = &dpi->output; |
| @@ -775,7 +776,7 @@ static void dpi_init_output_port(struct platform_device *pdev, | |||
| 775 | omapdss_register_output(out); | 776 | omapdss_register_output(out); |
| 776 | } | 777 | } |
| 777 | 778 | ||
| 778 | static void __exit dpi_uninit_output_port(struct device_node *port) | 779 | static void dpi_uninit_output_port(struct device_node *port) |
| 779 | { | 780 | { |
| 780 | struct dpi_data *dpi = port->data; | 781 | struct dpi_data *dpi = port->data; |
| 781 | struct omap_dss_device *out = &dpi->output; | 782 | struct omap_dss_device *out = &dpi->output; |
| @@ -783,8 +784,9 @@ static void __exit dpi_uninit_output_port(struct device_node *port) | |||
| 783 | omapdss_unregister_output(out); | 784 | omapdss_unregister_output(out); |
| 784 | } | 785 | } |
| 785 | 786 | ||
| 786 | static int omap_dpi_probe(struct platform_device *pdev) | 787 | static int dpi_bind(struct device *dev, struct device *master, void *data) |
| 787 | { | 788 | { |
| 789 | struct platform_device *pdev = to_platform_device(dev); | ||
| 788 | struct dpi_data *dpi; | 790 | struct dpi_data *dpi; |
| 789 | 791 | ||
| 790 | dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL); | 792 | dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL); |
| @@ -802,16 +804,32 @@ static int omap_dpi_probe(struct platform_device *pdev) | |||
| 802 | return 0; | 804 | return 0; |
| 803 | } | 805 | } |
| 804 | 806 | ||
| 805 | static int __exit omap_dpi_remove(struct platform_device *pdev) | 807 | static void dpi_unbind(struct device *dev, struct device *master, void *data) |
| 806 | { | 808 | { |
| 809 | struct platform_device *pdev = to_platform_device(dev); | ||
| 810 | |||
| 807 | dpi_uninit_output(pdev); | 811 | dpi_uninit_output(pdev); |
| 812 | } | ||
| 813 | |||
| 814 | static const struct component_ops dpi_component_ops = { | ||
| 815 | .bind = dpi_bind, | ||
| 816 | .unbind = dpi_unbind, | ||
| 817 | }; | ||
| 808 | 818 | ||
| 819 | static int dpi_probe(struct platform_device *pdev) | ||
| 820 | { | ||
| 821 | return component_add(&pdev->dev, &dpi_component_ops); | ||
| 822 | } | ||
| 823 | |||
| 824 | static int dpi_remove(struct platform_device *pdev) | ||
| 825 | { | ||
| 826 | component_del(&pdev->dev, &dpi_component_ops); | ||
| 809 | return 0; | 827 | return 0; |
| 810 | } | 828 | } |
| 811 | 829 | ||
| 812 | static struct platform_driver omap_dpi_driver = { | 830 | static struct platform_driver omap_dpi_driver = { |
| 813 | .probe = omap_dpi_probe, | 831 | .probe = dpi_probe, |
| 814 | .remove = __exit_p(omap_dpi_remove), | 832 | .remove = dpi_remove, |
| 815 | .driver = { | 833 | .driver = { |
| 816 | .name = "omapdss_dpi", | 834 | .name = "omapdss_dpi", |
| 817 | .suppress_bind_attrs = true, | 835 | .suppress_bind_attrs = true, |
| @@ -823,12 +841,12 @@ int __init dpi_init_platform_driver(void) | |||
| 823 | return platform_driver_register(&omap_dpi_driver); | 841 | return platform_driver_register(&omap_dpi_driver); |
| 824 | } | 842 | } |
| 825 | 843 | ||
| 826 | void __exit dpi_uninit_platform_driver(void) | 844 | void dpi_uninit_platform_driver(void) |
| 827 | { | 845 | { |
| 828 | platform_driver_unregister(&omap_dpi_driver); | 846 | platform_driver_unregister(&omap_dpi_driver); |
| 829 | } | 847 | } |
| 830 | 848 | ||
| 831 | int __init dpi_init_port(struct platform_device *pdev, struct device_node *port) | 849 | int dpi_init_port(struct platform_device *pdev, struct device_node *port) |
| 832 | { | 850 | { |
| 833 | struct dpi_data *dpi; | 851 | struct dpi_data *dpi; |
| 834 | struct device_node *ep; | 852 | struct device_node *ep; |
| @@ -870,7 +888,7 @@ err_datalines: | |||
| 870 | return r; | 888 | return r; |
| 871 | } | 889 | } |
| 872 | 890 | ||
| 873 | void __exit dpi_uninit_port(struct device_node *port) | 891 | void dpi_uninit_port(struct device_node *port) |
| 874 | { | 892 | { |
| 875 | struct dpi_data *dpi = port->data; | 893 | struct dpi_data *dpi = port->data; |
| 876 | 894 | ||
diff --git a/drivers/video/fbdev/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c index 28b0bc11669d..b3606def5b7b 100644 --- a/drivers/video/fbdev/omap2/dss/dsi.c +++ b/drivers/video/fbdev/omap2/dss/dsi.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
| 41 | #include <linux/of.h> | 41 | #include <linux/of.h> |
| 42 | #include <linux/of_platform.h> | 42 | #include <linux/of_platform.h> |
| 43 | #include <linux/component.h> | ||
| 43 | 44 | ||
| 44 | #include <video/omapdss.h> | 45 | #include <video/omapdss.h> |
| 45 | #include <video/mipi_display.h> | 46 | #include <video/mipi_display.h> |
| @@ -5274,8 +5275,9 @@ static int dsi_init_pll_data(struct platform_device *dsidev) | |||
| 5274 | } | 5275 | } |
| 5275 | 5276 | ||
| 5276 | /* DSI1 HW IP initialisation */ | 5277 | /* DSI1 HW IP initialisation */ |
| 5277 | static int omap_dsihw_probe(struct platform_device *dsidev) | 5278 | static int dsi_bind(struct device *dev, struct device *master, void *data) |
| 5278 | { | 5279 | { |
| 5280 | struct platform_device *dsidev = to_platform_device(dev); | ||
| 5279 | u32 rev; | 5281 | u32 rev; |
| 5280 | int r, i; | 5282 | int r, i; |
| 5281 | struct dsi_data *dsi; | 5283 | struct dsi_data *dsi; |
| @@ -5484,8 +5486,9 @@ err_runtime_get: | |||
| 5484 | return r; | 5486 | return r; |
| 5485 | } | 5487 | } |
| 5486 | 5488 | ||
| 5487 | static int __exit omap_dsihw_remove(struct platform_device *dsidev) | 5489 | static void dsi_unbind(struct device *dev, struct device *master, void *data) |
| 5488 | { | 5490 | { |
| 5491 | struct platform_device *dsidev = to_platform_device(dev); | ||
| 5489 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 5492 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 5490 | 5493 | ||
| 5491 | of_platform_depopulate(&dsidev->dev); | 5494 | of_platform_depopulate(&dsidev->dev); |
| @@ -5502,7 +5505,21 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev) | |||
| 5502 | regulator_disable(dsi->vdds_dsi_reg); | 5505 | regulator_disable(dsi->vdds_dsi_reg); |
| 5503 | dsi->vdds_dsi_enabled = false; | 5506 | dsi->vdds_dsi_enabled = false; |
| 5504 | } | 5507 | } |
| 5508 | } | ||
| 5509 | |||
| 5510 | static const struct component_ops dsi_component_ops = { | ||
| 5511 | .bind = dsi_bind, | ||
| 5512 | .unbind = dsi_unbind, | ||
| 5513 | }; | ||
| 5505 | 5514 | ||
| 5515 | static int dsi_probe(struct platform_device *pdev) | ||
| 5516 | { | ||
| 5517 | return component_add(&pdev->dev, &dsi_component_ops); | ||
| 5518 | } | ||
| 5519 | |||
| 5520 | static int dsi_remove(struct platform_device *pdev) | ||
| 5521 | { | ||
| 5522 | component_del(&pdev->dev, &dsi_component_ops); | ||
| 5506 | return 0; | 5523 | return 0; |
| 5507 | } | 5524 | } |
| 5508 | 5525 | ||
| @@ -5569,8 +5586,8 @@ static const struct of_device_id dsi_of_match[] = { | |||
| 5569 | }; | 5586 | }; |
| 5570 | 5587 | ||
| 5571 | static struct platform_driver omap_dsihw_driver = { | 5588 | static struct platform_driver omap_dsihw_driver = { |
| 5572 | .probe = omap_dsihw_probe, | 5589 | .probe = dsi_probe, |
| 5573 | .remove = __exit_p(omap_dsihw_remove), | 5590 | .remove = dsi_remove, |
| 5574 | .driver = { | 5591 | .driver = { |
| 5575 | .name = "omapdss_dsi", | 5592 | .name = "omapdss_dsi", |
| 5576 | .pm = &dsi_pm_ops, | 5593 | .pm = &dsi_pm_ops, |
| @@ -5584,7 +5601,7 @@ int __init dsi_init_platform_driver(void) | |||
| 5584 | return platform_driver_register(&omap_dsihw_driver); | 5601 | return platform_driver_register(&omap_dsihw_driver); |
| 5585 | } | 5602 | } |
| 5586 | 5603 | ||
| 5587 | void __exit dsi_uninit_platform_driver(void) | 5604 | void dsi_uninit_platform_driver(void) |
| 5588 | { | 5605 | { |
| 5589 | platform_driver_unregister(&omap_dsihw_driver); | 5606 | platform_driver_unregister(&omap_dsihw_driver); |
| 5590 | } | 5607 | } |
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c index 7f978b6a34e8..9200a8668b49 100644 --- a/drivers/video/fbdev/omap2/dss/dss.c +++ b/drivers/video/fbdev/omap2/dss/dss.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/of.h> | 39 | #include <linux/of.h> |
| 40 | #include <linux/regulator/consumer.h> | 40 | #include <linux/regulator/consumer.h> |
| 41 | #include <linux/suspend.h> | 41 | #include <linux/suspend.h> |
| 42 | #include <linux/component.h> | ||
| 42 | 43 | ||
| 43 | #include <video/omapdss.h> | 44 | #include <video/omapdss.h> |
| 44 | 45 | ||
| @@ -111,6 +112,14 @@ static const char * const dss_generic_clk_source_names[] = { | |||
| 111 | [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI", | 112 | [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI", |
| 112 | }; | 113 | }; |
| 113 | 114 | ||
| 115 | static bool dss_initialized; | ||
| 116 | |||
| 117 | bool omapdss_is_initialized(void) | ||
| 118 | { | ||
| 119 | return dss_initialized; | ||
| 120 | } | ||
| 121 | EXPORT_SYMBOL(omapdss_is_initialized); | ||
| 122 | |||
| 114 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) | 123 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) |
| 115 | { | 124 | { |
| 116 | __raw_writel(val, dss.base + idx.idx); | 125 | __raw_writel(val, dss.base + idx.idx); |
| @@ -811,7 +820,7 @@ static const enum omap_display_type dra7xx_ports[] = { | |||
| 811 | OMAP_DISPLAY_TYPE_DPI, | 820 | OMAP_DISPLAY_TYPE_DPI, |
| 812 | }; | 821 | }; |
| 813 | 822 | ||
| 814 | static const struct dss_features omap24xx_dss_feats __initconst = { | 823 | static const struct dss_features omap24xx_dss_feats = { |
| 815 | /* | 824 | /* |
| 816 | * fck div max is really 16, but the divider range has gaps. The range | 825 | * fck div max is really 16, but the divider range has gaps. The range |
| 817 | * from 1 to 6 has no gaps, so let's use that as a max. | 826 | * from 1 to 6 has no gaps, so let's use that as a max. |
| @@ -824,7 +833,7 @@ static const struct dss_features omap24xx_dss_feats __initconst = { | |||
| 824 | .num_ports = ARRAY_SIZE(omap2plus_ports), | 833 | .num_ports = ARRAY_SIZE(omap2plus_ports), |
| 825 | }; | 834 | }; |
| 826 | 835 | ||
| 827 | static const struct dss_features omap34xx_dss_feats __initconst = { | 836 | static const struct dss_features omap34xx_dss_feats = { |
| 828 | .fck_div_max = 16, | 837 | .fck_div_max = 16, |
| 829 | .dss_fck_multiplier = 2, | 838 | .dss_fck_multiplier = 2, |
| 830 | .parent_clk_name = "dpll4_ck", | 839 | .parent_clk_name = "dpll4_ck", |
| @@ -833,7 +842,7 @@ static const struct dss_features omap34xx_dss_feats __initconst = { | |||
| 833 | .num_ports = ARRAY_SIZE(omap34xx_ports), | 842 | .num_ports = ARRAY_SIZE(omap34xx_ports), |
| 834 | }; | 843 | }; |
| 835 | 844 | ||
| 836 | static const struct dss_features omap3630_dss_feats __initconst = { | 845 | static const struct dss_features omap3630_dss_feats = { |
| 837 | .fck_div_max = 32, | 846 | .fck_div_max = 32, |
| 838 | .dss_fck_multiplier = 1, | 847 | .dss_fck_multiplier = 1, |
| 839 | .parent_clk_name = "dpll4_ck", | 848 | .parent_clk_name = "dpll4_ck", |
| @@ -842,7 +851,7 @@ static const struct dss_features omap3630_dss_feats __initconst = { | |||
| 842 | .num_ports = ARRAY_SIZE(omap2plus_ports), | 851 | .num_ports = ARRAY_SIZE(omap2plus_ports), |
| 843 | }; | 852 | }; |
| 844 | 853 | ||
| 845 | static const struct dss_features omap44xx_dss_feats __initconst = { | 854 | static const struct dss_features omap44xx_dss_feats = { |
| 846 | .fck_div_max = 32, | 855 | .fck_div_max = 32, |
| 847 | .dss_fck_multiplier = 1, | 856 | .dss_fck_multiplier = 1, |
| 848 | .parent_clk_name = "dpll_per_x2_ck", | 857 | .parent_clk_name = "dpll_per_x2_ck", |
| @@ -851,7 +860,7 @@ static const struct dss_features omap44xx_dss_feats __initconst = { | |||
| 851 | .num_ports = ARRAY_SIZE(omap2plus_ports), | 860 | .num_ports = ARRAY_SIZE(omap2plus_ports), |
| 852 | }; | 861 | }; |
| 853 | 862 | ||
| 854 | static const struct dss_features omap54xx_dss_feats __initconst = { | 863 | static const struct dss_features omap54xx_dss_feats = { |
| 855 | .fck_div_max = 64, | 864 | .fck_div_max = 64, |
| 856 | .dss_fck_multiplier = 1, | 865 | .dss_fck_multiplier = 1, |
| 857 | .parent_clk_name = "dpll_per_x2_ck", | 866 | .parent_clk_name = "dpll_per_x2_ck", |
| @@ -860,7 +869,7 @@ static const struct dss_features omap54xx_dss_feats __initconst = { | |||
| 860 | .num_ports = ARRAY_SIZE(omap2plus_ports), | 869 | .num_ports = ARRAY_SIZE(omap2plus_ports), |
| 861 | }; | 870 | }; |
| 862 | 871 | ||
| 863 | static const struct dss_features am43xx_dss_feats __initconst = { | 872 | static const struct dss_features am43xx_dss_feats = { |
| 864 | .fck_div_max = 0, | 873 | .fck_div_max = 0, |
| 865 | .dss_fck_multiplier = 0, | 874 | .dss_fck_multiplier = 0, |
| 866 | .parent_clk_name = NULL, | 875 | .parent_clk_name = NULL, |
| @@ -869,7 +878,7 @@ static const struct dss_features am43xx_dss_feats __initconst = { | |||
| 869 | .num_ports = ARRAY_SIZE(omap2plus_ports), | 878 | .num_ports = ARRAY_SIZE(omap2plus_ports), |
| 870 | }; | 879 | }; |
| 871 | 880 | ||
| 872 | static const struct dss_features dra7xx_dss_feats __initconst = { | 881 | static const struct dss_features dra7xx_dss_feats = { |
| 873 | .fck_div_max = 64, | 882 | .fck_div_max = 64, |
| 874 | .dss_fck_multiplier = 1, | 883 | .dss_fck_multiplier = 1, |
| 875 | .parent_clk_name = "dpll_per_x2_ck", | 884 | .parent_clk_name = "dpll_per_x2_ck", |
| @@ -878,7 +887,7 @@ static const struct dss_features dra7xx_dss_feats __initconst = { | |||
| 878 | .num_ports = ARRAY_SIZE(dra7xx_ports), | 887 | .num_ports = ARRAY_SIZE(dra7xx_ports), |
| 879 | }; | 888 | }; |
| 880 | 889 | ||
| 881 | static int __init dss_init_features(struct platform_device *pdev) | 890 | static int dss_init_features(struct platform_device *pdev) |
| 882 | { | 891 | { |
| 883 | const struct dss_features *src; | 892 | const struct dss_features *src; |
| 884 | struct dss_features *dst; | 893 | struct dss_features *dst; |
| @@ -932,7 +941,7 @@ static int __init dss_init_features(struct platform_device *pdev) | |||
| 932 | return 0; | 941 | return 0; |
| 933 | } | 942 | } |
| 934 | 943 | ||
| 935 | static int __init dss_init_ports(struct platform_device *pdev) | 944 | static int dss_init_ports(struct platform_device *pdev) |
| 936 | { | 945 | { |
| 937 | struct device_node *parent = pdev->dev.of_node; | 946 | struct device_node *parent = pdev->dev.of_node; |
| 938 | struct device_node *port; | 947 | struct device_node *port; |
| @@ -976,7 +985,7 @@ static int __init dss_init_ports(struct platform_device *pdev) | |||
| 976 | return 0; | 985 | return 0; |
| 977 | } | 986 | } |
| 978 | 987 | ||
| 979 | static void __exit dss_uninit_ports(struct platform_device *pdev) | 988 | static void dss_uninit_ports(struct platform_device *pdev) |
| 980 | { | 989 | { |
| 981 | struct device_node *parent = pdev->dev.of_node; | 990 | struct device_node *parent = pdev->dev.of_node; |
| 982 | struct device_node *port; | 991 | struct device_node *port; |
| @@ -1018,14 +1027,74 @@ static void __exit dss_uninit_ports(struct platform_device *pdev) | |||
| 1018 | } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); | 1027 | } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); |
| 1019 | } | 1028 | } |
| 1020 | 1029 | ||
| 1030 | static int dss_video_pll_probe(struct platform_device *pdev) | ||
| 1031 | { | ||
| 1032 | struct device_node *np = pdev->dev.of_node; | ||
| 1033 | struct regulator *pll_regulator; | ||
| 1034 | int r; | ||
| 1035 | |||
| 1036 | if (!np) | ||
| 1037 | return 0; | ||
| 1038 | |||
| 1039 | if (of_property_read_bool(np, "syscon-pll-ctrl")) { | ||
| 1040 | dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np, | ||
| 1041 | "syscon-pll-ctrl"); | ||
| 1042 | if (IS_ERR(dss.syscon_pll_ctrl)) { | ||
| 1043 | dev_err(&pdev->dev, | ||
| 1044 | "failed to get syscon-pll-ctrl regmap\n"); | ||
| 1045 | return PTR_ERR(dss.syscon_pll_ctrl); | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1, | ||
| 1049 | &dss.syscon_pll_ctrl_offset)) { | ||
| 1050 | dev_err(&pdev->dev, | ||
| 1051 | "failed to get syscon-pll-ctrl offset\n"); | ||
| 1052 | return -EINVAL; | ||
| 1053 | } | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video"); | ||
| 1057 | if (IS_ERR(pll_regulator)) { | ||
| 1058 | r = PTR_ERR(pll_regulator); | ||
| 1059 | |||
| 1060 | switch (r) { | ||
| 1061 | case -ENOENT: | ||
| 1062 | pll_regulator = NULL; | ||
| 1063 | break; | ||
| 1064 | |||
| 1065 | case -EPROBE_DEFER: | ||
| 1066 | return -EPROBE_DEFER; | ||
| 1067 | |||
| 1068 | default: | ||
| 1069 | DSSERR("can't get DPLL VDDA regulator\n"); | ||
| 1070 | return r; | ||
| 1071 | } | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | if (of_property_match_string(np, "reg-names", "pll1") >= 0) { | ||
| 1075 | dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator); | ||
| 1076 | if (IS_ERR(dss.video1_pll)) | ||
| 1077 | return PTR_ERR(dss.video1_pll); | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | if (of_property_match_string(np, "reg-names", "pll2") >= 0) { | ||
| 1081 | dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator); | ||
| 1082 | if (IS_ERR(dss.video2_pll)) { | ||
| 1083 | dss_video_pll_uninit(dss.video1_pll); | ||
| 1084 | return PTR_ERR(dss.video2_pll); | ||
| 1085 | } | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | return 0; | ||
| 1089 | } | ||
| 1090 | |||
| 1021 | /* DSS HW IP initialisation */ | 1091 | /* DSS HW IP initialisation */ |
| 1022 | static int __init omap_dsshw_probe(struct platform_device *pdev) | 1092 | static int dss_bind(struct device *dev) |
| 1023 | { | 1093 | { |
| 1094 | struct platform_device *pdev = to_platform_device(dev); | ||
| 1024 | struct resource *dss_mem; | 1095 | struct resource *dss_mem; |
| 1025 | struct device_node *np = pdev->dev.of_node; | ||
| 1026 | u32 rev; | 1096 | u32 rev; |
| 1027 | int r; | 1097 | int r; |
| 1028 | struct regulator *pll_regulator; | ||
| 1029 | 1098 | ||
| 1030 | dss.pdev = pdev; | 1099 | dss.pdev = pdev; |
| 1031 | 1100 | ||
| @@ -1054,6 +1123,14 @@ static int __init omap_dsshw_probe(struct platform_device *pdev) | |||
| 1054 | if (r) | 1123 | if (r) |
| 1055 | goto err_setup_clocks; | 1124 | goto err_setup_clocks; |
| 1056 | 1125 | ||
| 1126 | r = dss_video_pll_probe(pdev); | ||
| 1127 | if (r) | ||
| 1128 | goto err_pll_init; | ||
| 1129 | |||
| 1130 | r = dss_init_ports(pdev); | ||
| 1131 | if (r) | ||
| 1132 | goto err_init_ports; | ||
| 1133 | |||
| 1057 | pm_runtime_enable(&pdev->dev); | 1134 | pm_runtime_enable(&pdev->dev); |
| 1058 | 1135 | ||
| 1059 | r = dss_runtime_get(); | 1136 | r = dss_runtime_get(); |
| @@ -1078,86 +1155,48 @@ static int __init omap_dsshw_probe(struct platform_device *pdev) | |||
| 1078 | dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; | 1155 | dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; |
| 1079 | dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; | 1156 | dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; |
| 1080 | 1157 | ||
| 1081 | dss_init_ports(pdev); | ||
| 1082 | |||
| 1083 | if (np && of_property_read_bool(np, "syscon-pll-ctrl")) { | ||
| 1084 | dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np, | ||
| 1085 | "syscon-pll-ctrl"); | ||
| 1086 | if (IS_ERR(dss.syscon_pll_ctrl)) { | ||
| 1087 | dev_err(&pdev->dev, | ||
| 1088 | "failed to get syscon-pll-ctrl regmap\n"); | ||
| 1089 | return PTR_ERR(dss.syscon_pll_ctrl); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1, | ||
| 1093 | &dss.syscon_pll_ctrl_offset)) { | ||
| 1094 | dev_err(&pdev->dev, | ||
| 1095 | "failed to get syscon-pll-ctrl offset\n"); | ||
| 1096 | return -EINVAL; | ||
| 1097 | } | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video"); | ||
| 1101 | if (IS_ERR(pll_regulator)) { | ||
| 1102 | r = PTR_ERR(pll_regulator); | ||
| 1103 | |||
| 1104 | switch (r) { | ||
| 1105 | case -ENOENT: | ||
| 1106 | pll_regulator = NULL; | ||
| 1107 | break; | ||
| 1108 | |||
| 1109 | case -EPROBE_DEFER: | ||
| 1110 | return -EPROBE_DEFER; | ||
| 1111 | |||
| 1112 | default: | ||
| 1113 | DSSERR("can't get DPLL VDDA regulator\n"); | ||
| 1114 | return r; | ||
| 1115 | } | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | if (of_property_match_string(np, "reg-names", "pll1") >= 0) { | ||
| 1119 | dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator); | ||
| 1120 | if (IS_ERR(dss.video1_pll)) { | ||
| 1121 | r = PTR_ERR(dss.video1_pll); | ||
| 1122 | goto err_pll_init; | ||
| 1123 | } | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | if (of_property_match_string(np, "reg-names", "pll2") >= 0) { | ||
| 1127 | dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator); | ||
| 1128 | if (IS_ERR(dss.video2_pll)) { | ||
| 1129 | r = PTR_ERR(dss.video2_pll); | ||
| 1130 | goto err_pll_init; | ||
| 1131 | } | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | rev = dss_read_reg(DSS_REVISION); | 1158 | rev = dss_read_reg(DSS_REVISION); |
| 1135 | printk(KERN_INFO "OMAP DSS rev %d.%d\n", | 1159 | printk(KERN_INFO "OMAP DSS rev %d.%d\n", |
| 1136 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 1160 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
| 1137 | 1161 | ||
| 1138 | dss_runtime_put(); | 1162 | dss_runtime_put(); |
| 1139 | 1163 | ||
| 1164 | r = component_bind_all(&pdev->dev, NULL); | ||
| 1165 | if (r) | ||
| 1166 | goto err_component; | ||
| 1167 | |||
| 1140 | dss_debugfs_create_file("dss", dss_dump_regs); | 1168 | dss_debugfs_create_file("dss", dss_dump_regs); |
| 1141 | 1169 | ||
| 1142 | pm_set_vt_switch(0); | 1170 | pm_set_vt_switch(0); |
| 1143 | 1171 | ||
| 1172 | dss_initialized = true; | ||
| 1173 | |||
| 1144 | return 0; | 1174 | return 0; |
| 1145 | 1175 | ||
| 1146 | err_pll_init: | 1176 | err_component: |
| 1177 | err_runtime_get: | ||
| 1178 | pm_runtime_disable(&pdev->dev); | ||
| 1179 | dss_uninit_ports(pdev); | ||
| 1180 | err_init_ports: | ||
| 1147 | if (dss.video1_pll) | 1181 | if (dss.video1_pll) |
| 1148 | dss_video_pll_uninit(dss.video1_pll); | 1182 | dss_video_pll_uninit(dss.video1_pll); |
| 1149 | 1183 | ||
| 1150 | if (dss.video2_pll) | 1184 | if (dss.video2_pll) |
| 1151 | dss_video_pll_uninit(dss.video2_pll); | 1185 | dss_video_pll_uninit(dss.video2_pll); |
| 1152 | err_runtime_get: | 1186 | err_pll_init: |
| 1153 | pm_runtime_disable(&pdev->dev); | ||
| 1154 | err_setup_clocks: | 1187 | err_setup_clocks: |
| 1155 | dss_put_clocks(); | 1188 | dss_put_clocks(); |
| 1156 | return r; | 1189 | return r; |
| 1157 | } | 1190 | } |
| 1158 | 1191 | ||
| 1159 | static int __exit omap_dsshw_remove(struct platform_device *pdev) | 1192 | static void dss_unbind(struct device *dev) |
| 1160 | { | 1193 | { |
| 1194 | struct platform_device *pdev = to_platform_device(dev); | ||
| 1195 | |||
| 1196 | dss_initialized = false; | ||
| 1197 | |||
| 1198 | component_unbind_all(&pdev->dev, NULL); | ||
| 1199 | |||
| 1161 | if (dss.video1_pll) | 1200 | if (dss.video1_pll) |
| 1162 | dss_video_pll_uninit(dss.video1_pll); | 1201 | dss_video_pll_uninit(dss.video1_pll); |
| 1163 | 1202 | ||
| @@ -1169,7 +1208,55 @@ static int __exit omap_dsshw_remove(struct platform_device *pdev) | |||
| 1169 | pm_runtime_disable(&pdev->dev); | 1208 | pm_runtime_disable(&pdev->dev); |
| 1170 | 1209 | ||
| 1171 | dss_put_clocks(); | 1210 | dss_put_clocks(); |
| 1211 | } | ||
| 1212 | |||
| 1213 | static const struct component_master_ops dss_component_ops = { | ||
| 1214 | .bind = dss_bind, | ||
| 1215 | .unbind = dss_unbind, | ||
| 1216 | }; | ||
| 1172 | 1217 | ||
| 1218 | static int dss_component_compare(struct device *dev, void *data) | ||
| 1219 | { | ||
| 1220 | struct device *child = data; | ||
| 1221 | return dev == child; | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | static int dss_add_child_component(struct device *dev, void *data) | ||
| 1225 | { | ||
| 1226 | struct component_match **match = data; | ||
| 1227 | |||
| 1228 | /* | ||
| 1229 | * HACK | ||
| 1230 | * We don't have a working driver for rfbi, so skip it here always. | ||
| 1231 | * Otherwise dss will never get probed successfully, as it will wait | ||
| 1232 | * for rfbi to get probed. | ||
| 1233 | */ | ||
| 1234 | if (strstr(dev_name(dev), "rfbi")) | ||
| 1235 | return 0; | ||
| 1236 | |||
| 1237 | component_match_add(dev->parent, match, dss_component_compare, dev); | ||
| 1238 | |||
| 1239 | return 0; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static int dss_probe(struct platform_device *pdev) | ||
| 1243 | { | ||
| 1244 | struct component_match *match = NULL; | ||
| 1245 | int r; | ||
| 1246 | |||
| 1247 | /* add all the child devices as components */ | ||
| 1248 | device_for_each_child(&pdev->dev, &match, dss_add_child_component); | ||
| 1249 | |||
| 1250 | r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match); | ||
| 1251 | if (r) | ||
| 1252 | return r; | ||
| 1253 | |||
| 1254 | return 0; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | static int dss_remove(struct platform_device *pdev) | ||
| 1258 | { | ||
| 1259 | component_master_del(&pdev->dev, &dss_component_ops); | ||
| 1173 | return 0; | 1260 | return 0; |
| 1174 | } | 1261 | } |
| 1175 | 1262 | ||
| @@ -1215,7 +1302,8 @@ static const struct of_device_id dss_of_match[] = { | |||
| 1215 | MODULE_DEVICE_TABLE(of, dss_of_match); | 1302 | MODULE_DEVICE_TABLE(of, dss_of_match); |
| 1216 | 1303 | ||
| 1217 | static struct platform_driver omap_dsshw_driver = { | 1304 | static struct platform_driver omap_dsshw_driver = { |
| 1218 | .remove = __exit_p(omap_dsshw_remove), | 1305 | .probe = dss_probe, |
| 1306 | .remove = dss_remove, | ||
| 1219 | .driver = { | 1307 | .driver = { |
| 1220 | .name = "omapdss_dss", | 1308 | .name = "omapdss_dss", |
| 1221 | .pm = &dss_pm_ops, | 1309 | .pm = &dss_pm_ops, |
| @@ -1226,7 +1314,7 @@ static struct platform_driver omap_dsshw_driver = { | |||
| 1226 | 1314 | ||
| 1227 | int __init dss_init_platform_driver(void) | 1315 | int __init dss_init_platform_driver(void) |
| 1228 | { | 1316 | { |
| 1229 | return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe); | 1317 | return platform_driver_register(&omap_dsshw_driver); |
| 1230 | } | 1318 | } |
| 1231 | 1319 | ||
| 1232 | void dss_uninit_platform_driver(void) | 1320 | void dss_uninit_platform_driver(void) |
diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h index 4812eee2622a..2406bcdb831a 100644 --- a/drivers/video/fbdev/omap2/dss/dss.h +++ b/drivers/video/fbdev/omap2/dss/dss.h | |||
| @@ -309,18 +309,18 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min, | |||
| 309 | 309 | ||
| 310 | /* SDI */ | 310 | /* SDI */ |
| 311 | int sdi_init_platform_driver(void) __init; | 311 | int sdi_init_platform_driver(void) __init; |
| 312 | void sdi_uninit_platform_driver(void) __exit; | 312 | void sdi_uninit_platform_driver(void); |
| 313 | 313 | ||
| 314 | #ifdef CONFIG_OMAP2_DSS_SDI | 314 | #ifdef CONFIG_OMAP2_DSS_SDI |
| 315 | int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init; | 315 | int sdi_init_port(struct platform_device *pdev, struct device_node *port); |
| 316 | void sdi_uninit_port(struct device_node *port) __exit; | 316 | void sdi_uninit_port(struct device_node *port); |
| 317 | #else | 317 | #else |
| 318 | static inline int __init sdi_init_port(struct platform_device *pdev, | 318 | static inline int sdi_init_port(struct platform_device *pdev, |
| 319 | struct device_node *port) | 319 | struct device_node *port) |
| 320 | { | 320 | { |
| 321 | return 0; | 321 | return 0; |
| 322 | } | 322 | } |
| 323 | static inline void __exit sdi_uninit_port(struct device_node *port) | 323 | static inline void sdi_uninit_port(struct device_node *port) |
| 324 | { | 324 | { |
| 325 | } | 325 | } |
| 326 | #endif | 326 | #endif |
| @@ -333,7 +333,7 @@ struct dentry; | |||
| 333 | struct file_operations; | 333 | struct file_operations; |
| 334 | 334 | ||
| 335 | int dsi_init_platform_driver(void) __init; | 335 | int dsi_init_platform_driver(void) __init; |
| 336 | void dsi_uninit_platform_driver(void) __exit; | 336 | void dsi_uninit_platform_driver(void); |
| 337 | 337 | ||
| 338 | void dsi_dump_clocks(struct seq_file *s); | 338 | void dsi_dump_clocks(struct seq_file *s); |
| 339 | 339 | ||
| @@ -350,25 +350,25 @@ static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) | |||
| 350 | 350 | ||
| 351 | /* DPI */ | 351 | /* DPI */ |
| 352 | int dpi_init_platform_driver(void) __init; | 352 | int dpi_init_platform_driver(void) __init; |
| 353 | void dpi_uninit_platform_driver(void) __exit; | 353 | void dpi_uninit_platform_driver(void); |
| 354 | 354 | ||
| 355 | #ifdef CONFIG_OMAP2_DSS_DPI | 355 | #ifdef CONFIG_OMAP2_DSS_DPI |
| 356 | int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init; | 356 | int dpi_init_port(struct platform_device *pdev, struct device_node *port); |
| 357 | void dpi_uninit_port(struct device_node *port) __exit; | 357 | void dpi_uninit_port(struct device_node *port); |
| 358 | #else | 358 | #else |
| 359 | static inline int __init dpi_init_port(struct platform_device *pdev, | 359 | static inline int dpi_init_port(struct platform_device *pdev, |
| 360 | struct device_node *port) | 360 | struct device_node *port) |
| 361 | { | 361 | { |
| 362 | return 0; | 362 | return 0; |
| 363 | } | 363 | } |
| 364 | static inline void __exit dpi_uninit_port(struct device_node *port) | 364 | static inline void dpi_uninit_port(struct device_node *port) |
| 365 | { | 365 | { |
| 366 | } | 366 | } |
| 367 | #endif | 367 | #endif |
| 368 | 368 | ||
| 369 | /* DISPC */ | 369 | /* DISPC */ |
| 370 | int dispc_init_platform_driver(void) __init; | 370 | int dispc_init_platform_driver(void) __init; |
| 371 | void dispc_uninit_platform_driver(void) __exit; | 371 | void dispc_uninit_platform_driver(void); |
| 372 | void dispc_dump_clocks(struct seq_file *s); | 372 | void dispc_dump_clocks(struct seq_file *s); |
| 373 | 373 | ||
| 374 | void dispc_enable_sidle(void); | 374 | void dispc_enable_sidle(void); |
| @@ -418,18 +418,18 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, | |||
| 418 | 418 | ||
| 419 | /* VENC */ | 419 | /* VENC */ |
| 420 | int venc_init_platform_driver(void) __init; | 420 | int venc_init_platform_driver(void) __init; |
| 421 | void venc_uninit_platform_driver(void) __exit; | 421 | void venc_uninit_platform_driver(void); |
| 422 | 422 | ||
| 423 | /* HDMI */ | 423 | /* HDMI */ |
| 424 | int hdmi4_init_platform_driver(void) __init; | 424 | int hdmi4_init_platform_driver(void) __init; |
| 425 | void hdmi4_uninit_platform_driver(void) __exit; | 425 | void hdmi4_uninit_platform_driver(void); |
| 426 | 426 | ||
| 427 | int hdmi5_init_platform_driver(void) __init; | 427 | int hdmi5_init_platform_driver(void) __init; |
| 428 | void hdmi5_uninit_platform_driver(void) __exit; | 428 | void hdmi5_uninit_platform_driver(void); |
| 429 | 429 | ||
| 430 | /* RFBI */ | 430 | /* RFBI */ |
| 431 | int rfbi_init_platform_driver(void) __init; | 431 | int rfbi_init_platform_driver(void) __init; |
| 432 | void rfbi_uninit_platform_driver(void) __exit; | 432 | void rfbi_uninit_platform_driver(void); |
| 433 | 433 | ||
| 434 | 434 | ||
| 435 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 435 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c index 916d47978f41..6d3aa3f51c20 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4.c +++ b/drivers/video/fbdev/omap2/dss/hdmi4.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/clk.h> | 32 | #include <linux/clk.h> |
| 33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
| 34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
| 35 | #include <linux/component.h> | ||
| 35 | #include <video/omapdss.h> | 36 | #include <video/omapdss.h> |
| 36 | #include <sound/omap-hdmi-audio.h> | 37 | #include <sound/omap-hdmi-audio.h> |
| 37 | 38 | ||
| @@ -229,9 +230,9 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) | |||
| 229 | err_mgr_enable: | 230 | err_mgr_enable: |
| 230 | hdmi_wp_video_stop(&hdmi.wp); | 231 | hdmi_wp_video_stop(&hdmi.wp); |
| 231 | err_vid_enable: | 232 | err_vid_enable: |
| 232 | err_phy_cfg: | ||
| 233 | hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); | 233 | hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); |
| 234 | err_phy_pwr: | 234 | err_phy_pwr: |
| 235 | err_phy_cfg: | ||
| 235 | err_pll_cfg: | 236 | err_pll_cfg: |
| 236 | dss_pll_disable(&hdmi.pll.pll); | 237 | dss_pll_disable(&hdmi.pll.pll); |
| 237 | err_pll_enable: | 238 | err_pll_enable: |
| @@ -646,8 +647,9 @@ static int hdmi_audio_register(struct device *dev) | |||
| 646 | } | 647 | } |
| 647 | 648 | ||
| 648 | /* HDMI HW IP initialisation */ | 649 | /* HDMI HW IP initialisation */ |
| 649 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 650 | static int hdmi4_bind(struct device *dev, struct device *master, void *data) |
| 650 | { | 651 | { |
| 652 | struct platform_device *pdev = to_platform_device(dev); | ||
| 651 | int r; | 653 | int r; |
| 652 | int irq; | 654 | int irq; |
| 653 | 655 | ||
| @@ -713,8 +715,10 @@ err: | |||
| 713 | return r; | 715 | return r; |
| 714 | } | 716 | } |
| 715 | 717 | ||
| 716 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | 718 | static void hdmi4_unbind(struct device *dev, struct device *master, void *data) |
| 717 | { | 719 | { |
| 720 | struct platform_device *pdev = to_platform_device(dev); | ||
| 721 | |||
| 718 | if (hdmi.audio_pdev) | 722 | if (hdmi.audio_pdev) |
| 719 | platform_device_unregister(hdmi.audio_pdev); | 723 | platform_device_unregister(hdmi.audio_pdev); |
| 720 | 724 | ||
| @@ -723,7 +727,21 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | |||
| 723 | hdmi_pll_uninit(&hdmi.pll); | 727 | hdmi_pll_uninit(&hdmi.pll); |
| 724 | 728 | ||
| 725 | pm_runtime_disable(&pdev->dev); | 729 | pm_runtime_disable(&pdev->dev); |
| 730 | } | ||
| 731 | |||
| 732 | static const struct component_ops hdmi4_component_ops = { | ||
| 733 | .bind = hdmi4_bind, | ||
| 734 | .unbind = hdmi4_unbind, | ||
| 735 | }; | ||
| 726 | 736 | ||
| 737 | static int hdmi4_probe(struct platform_device *pdev) | ||
| 738 | { | ||
| 739 | return component_add(&pdev->dev, &hdmi4_component_ops); | ||
| 740 | } | ||
| 741 | |||
| 742 | static int hdmi4_remove(struct platform_device *pdev) | ||
| 743 | { | ||
| 744 | component_del(&pdev->dev, &hdmi4_component_ops); | ||
| 727 | return 0; | 745 | return 0; |
| 728 | } | 746 | } |
| 729 | 747 | ||
| @@ -756,8 +774,8 @@ static const struct of_device_id hdmi_of_match[] = { | |||
| 756 | }; | 774 | }; |
| 757 | 775 | ||
| 758 | static struct platform_driver omapdss_hdmihw_driver = { | 776 | static struct platform_driver omapdss_hdmihw_driver = { |
| 759 | .probe = omapdss_hdmihw_probe, | 777 | .probe = hdmi4_probe, |
| 760 | .remove = __exit_p(omapdss_hdmihw_remove), | 778 | .remove = hdmi4_remove, |
| 761 | .driver = { | 779 | .driver = { |
| 762 | .name = "omapdss_hdmi", | 780 | .name = "omapdss_hdmi", |
| 763 | .pm = &hdmi_pm_ops, | 781 | .pm = &hdmi_pm_ops, |
| @@ -771,7 +789,7 @@ int __init hdmi4_init_platform_driver(void) | |||
| 771 | return platform_driver_register(&omapdss_hdmihw_driver); | 789 | return platform_driver_register(&omapdss_hdmihw_driver); |
| 772 | } | 790 | } |
| 773 | 791 | ||
| 774 | void __exit hdmi4_uninit_platform_driver(void) | 792 | void hdmi4_uninit_platform_driver(void) |
| 775 | { | 793 | { |
| 776 | platform_driver_unregister(&omapdss_hdmihw_driver); | 794 | platform_driver_unregister(&omapdss_hdmihw_driver); |
| 777 | } | 795 | } |
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.c b/drivers/video/fbdev/omap2/dss/hdmi4_core.c index 7eafea5b8e19..fa72e735dad2 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4_core.c +++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.c | |||
| @@ -654,6 +654,13 @@ static void hdmi_core_audio_infoframe_cfg(struct hdmi_core_data *core, | |||
| 654 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3); | 654 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3); |
| 655 | sum += info_aud->db3; | 655 | sum += info_aud->db3; |
| 656 | 656 | ||
| 657 | /* | ||
| 658 | * The OMAP HDMI IP requires to use the 8-channel channel code when | ||
| 659 | * transmitting more than two channels. | ||
| 660 | */ | ||
| 661 | if (info_aud->db4_ca != 0x00) | ||
| 662 | info_aud->db4_ca = 0x13; | ||
| 663 | |||
| 657 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca); | 664 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca); |
| 658 | sum += info_aud->db4_ca; | 665 | sum += info_aud->db4_ca; |
| 659 | 666 | ||
| @@ -795,7 +802,9 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, | |||
| 795 | 802 | ||
| 796 | /* | 803 | /* |
| 797 | * the HDMI IP needs to enable four stereo channels when transmitting | 804 | * the HDMI IP needs to enable four stereo channels when transmitting |
| 798 | * more than 2 audio channels | 805 | * more than 2 audio channels. Similarly, the channel count in the |
| 806 | * Audio InfoFrame has to match the sample_present bits (some channels | ||
| 807 | * are padded with zeroes) | ||
| 799 | */ | 808 | */ |
| 800 | if (channel_count == 2) { | 809 | if (channel_count == 2) { |
| 801 | audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; | 810 | audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; |
| @@ -807,6 +816,7 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, | |||
| 807 | HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN | | 816 | HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN | |
| 808 | HDMI_AUDIO_I2S_SD3_EN; | 817 | HDMI_AUDIO_I2S_SD3_EN; |
| 809 | acore.layout = HDMI_AUDIO_LAYOUT_8CH; | 818 | acore.layout = HDMI_AUDIO_LAYOUT_8CH; |
| 819 | audio->cea->db1_ct_cc = 7; | ||
| 810 | } | 820 | } |
| 811 | 821 | ||
| 812 | acore.en_spdif = false; | 822 | acore.en_spdif = false; |
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5.c b/drivers/video/fbdev/omap2/dss/hdmi5.c index 3f0b34a7031a..7f875788edbc 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5.c +++ b/drivers/video/fbdev/omap2/dss/hdmi5.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/clk.h> | 37 | #include <linux/clk.h> |
| 38 | #include <linux/gpio.h> | 38 | #include <linux/gpio.h> |
| 39 | #include <linux/regulator/consumer.h> | 39 | #include <linux/regulator/consumer.h> |
| 40 | #include <linux/component.h> | ||
| 40 | #include <video/omapdss.h> | 41 | #include <video/omapdss.h> |
| 41 | #include <sound/omap-hdmi-audio.h> | 42 | #include <sound/omap-hdmi-audio.h> |
| 42 | 43 | ||
| @@ -681,8 +682,9 @@ static int hdmi_audio_register(struct device *dev) | |||
| 681 | } | 682 | } |
| 682 | 683 | ||
| 683 | /* HDMI HW IP initialisation */ | 684 | /* HDMI HW IP initialisation */ |
| 684 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 685 | static int hdmi5_bind(struct device *dev, struct device *master, void *data) |
| 685 | { | 686 | { |
| 687 | struct platform_device *pdev = to_platform_device(dev); | ||
| 686 | int r; | 688 | int r; |
| 687 | int irq; | 689 | int irq; |
| 688 | 690 | ||
| @@ -748,8 +750,10 @@ err: | |||
| 748 | return r; | 750 | return r; |
| 749 | } | 751 | } |
| 750 | 752 | ||
| 751 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | 753 | static void hdmi5_unbind(struct device *dev, struct device *master, void *data) |
| 752 | { | 754 | { |
| 755 | struct platform_device *pdev = to_platform_device(dev); | ||
| 756 | |||
| 753 | if (hdmi.audio_pdev) | 757 | if (hdmi.audio_pdev) |
| 754 | platform_device_unregister(hdmi.audio_pdev); | 758 | platform_device_unregister(hdmi.audio_pdev); |
| 755 | 759 | ||
| @@ -758,7 +762,21 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | |||
| 758 | hdmi_pll_uninit(&hdmi.pll); | 762 | hdmi_pll_uninit(&hdmi.pll); |
| 759 | 763 | ||
| 760 | pm_runtime_disable(&pdev->dev); | 764 | pm_runtime_disable(&pdev->dev); |
| 765 | } | ||
| 766 | |||
| 767 | static const struct component_ops hdmi5_component_ops = { | ||
| 768 | .bind = hdmi5_bind, | ||
| 769 | .unbind = hdmi5_unbind, | ||
| 770 | }; | ||
| 761 | 771 | ||
| 772 | static int hdmi5_probe(struct platform_device *pdev) | ||
| 773 | { | ||
| 774 | return component_add(&pdev->dev, &hdmi5_component_ops); | ||
| 775 | } | ||
| 776 | |||
| 777 | static int hdmi5_remove(struct platform_device *pdev) | ||
| 778 | { | ||
| 779 | component_del(&pdev->dev, &hdmi5_component_ops); | ||
| 762 | return 0; | 780 | return 0; |
| 763 | } | 781 | } |
| 764 | 782 | ||
| @@ -792,8 +810,8 @@ static const struct of_device_id hdmi_of_match[] = { | |||
| 792 | }; | 810 | }; |
| 793 | 811 | ||
| 794 | static struct platform_driver omapdss_hdmihw_driver = { | 812 | static struct platform_driver omapdss_hdmihw_driver = { |
| 795 | .probe = omapdss_hdmihw_probe, | 813 | .probe = hdmi5_probe, |
| 796 | .remove = __exit_p(omapdss_hdmihw_remove), | 814 | .remove = hdmi5_remove, |
| 797 | .driver = { | 815 | .driver = { |
| 798 | .name = "omapdss_hdmi5", | 816 | .name = "omapdss_hdmi5", |
| 799 | .pm = &hdmi_pm_ops, | 817 | .pm = &hdmi_pm_ops, |
| @@ -807,7 +825,7 @@ int __init hdmi5_init_platform_driver(void) | |||
| 807 | return platform_driver_register(&omapdss_hdmihw_driver); | 825 | return platform_driver_register(&omapdss_hdmihw_driver); |
| 808 | } | 826 | } |
| 809 | 827 | ||
| 810 | void __exit hdmi5_uninit_platform_driver(void) | 828 | void hdmi5_uninit_platform_driver(void) |
| 811 | { | 829 | { |
| 812 | platform_driver_unregister(&omapdss_hdmihw_driver); | 830 | platform_driver_unregister(&omapdss_hdmihw_driver); |
| 813 | } | 831 | } |
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5_core.c b/drivers/video/fbdev/omap2/dss/hdmi5_core.c index bfc0c4c297d6..8ea531d2652c 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5_core.c +++ b/drivers/video/fbdev/omap2/dss/hdmi5_core.c | |||
| @@ -790,7 +790,9 @@ static void hdmi5_core_audio_infoframe_cfg(struct hdmi_core_data *core, | |||
| 790 | 790 | ||
| 791 | hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF1, info_aud->db2_sf_ss); | 791 | hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF1, info_aud->db2_sf_ss); |
| 792 | hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF2, info_aud->db4_ca); | 792 | hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF2, info_aud->db4_ca); |
| 793 | hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF3, info_aud->db5_dminh_lsv); | 793 | hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF3, |
| 794 | (info_aud->db5_dminh_lsv & CEA861_AUDIO_INFOFRAME_DB5_DM_INH) >> 3 | | ||
| 795 | (info_aud->db5_dminh_lsv & CEA861_AUDIO_INFOFRAME_DB5_LSV)); | ||
| 794 | } | 796 | } |
| 795 | 797 | ||
| 796 | int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, | 798 | int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, |
| @@ -870,6 +872,7 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, | |||
| 870 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; | 872 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; |
| 871 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; | 873 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; |
| 872 | audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; | 874 | audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; |
| 875 | audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; | ||
| 873 | 876 | ||
| 874 | /* only LPCM atm */ | 877 | /* only LPCM atm */ |
| 875 | audio_format.type = HDMI_AUDIO_TYPE_LPCM; | 878 | audio_format.type = HDMI_AUDIO_TYPE_LPCM; |
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_wp.c b/drivers/video/fbdev/omap2/dss/hdmi_wp.c index c15377e242cc..7c544bc56fb5 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_wp.c +++ b/drivers/video/fbdev/omap2/dss/hdmi_wp.c | |||
| @@ -110,7 +110,23 @@ int hdmi_wp_video_start(struct hdmi_wp_data *wp) | |||
| 110 | 110 | ||
| 111 | void hdmi_wp_video_stop(struct hdmi_wp_data *wp) | 111 | void hdmi_wp_video_stop(struct hdmi_wp_data *wp) |
| 112 | { | 112 | { |
| 113 | int i; | ||
| 114 | |||
| 115 | hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE); | ||
| 116 | |||
| 113 | REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31); | 117 | REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31); |
| 118 | |||
| 119 | for (i = 0; i < 50; ++i) { | ||
| 120 | u32 v; | ||
| 121 | |||
| 122 | msleep(20); | ||
| 123 | |||
| 124 | v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW); | ||
| 125 | if (v & HDMI_IRQ_VIDEO_FRAME_DONE) | ||
| 126 | return; | ||
| 127 | } | ||
| 128 | |||
| 129 | DSSERR("no HDMI FRAMEDONE when disabling output\n"); | ||
| 114 | } | 130 | } |
| 115 | 131 | ||
| 116 | void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, | 132 | void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, |
diff --git a/drivers/video/fbdev/omap2/dss/rfbi.c b/drivers/video/fbdev/omap2/dss/rfbi.c index 065effca9236..1525a494d057 100644 --- a/drivers/video/fbdev/omap2/dss/rfbi.c +++ b/drivers/video/fbdev/omap2/dss/rfbi.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/semaphore.h> | 36 | #include <linux/semaphore.h> |
| 37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
| 38 | #include <linux/pm_runtime.h> | 38 | #include <linux/pm_runtime.h> |
| 39 | #include <linux/component.h> | ||
| 39 | 40 | ||
| 40 | #include <video/omapdss.h> | 41 | #include <video/omapdss.h> |
| 41 | #include "dss.h" | 42 | #include "dss.h" |
| @@ -938,7 +939,7 @@ static void rfbi_init_output(struct platform_device *pdev) | |||
| 938 | omapdss_register_output(out); | 939 | omapdss_register_output(out); |
| 939 | } | 940 | } |
| 940 | 941 | ||
| 941 | static void __exit rfbi_uninit_output(struct platform_device *pdev) | 942 | static void rfbi_uninit_output(struct platform_device *pdev) |
| 942 | { | 943 | { |
| 943 | struct omap_dss_device *out = &rfbi.output; | 944 | struct omap_dss_device *out = &rfbi.output; |
| 944 | 945 | ||
| @@ -946,8 +947,9 @@ static void __exit rfbi_uninit_output(struct platform_device *pdev) | |||
| 946 | } | 947 | } |
| 947 | 948 | ||
| 948 | /* RFBI HW IP initialisation */ | 949 | /* RFBI HW IP initialisation */ |
| 949 | static int omap_rfbihw_probe(struct platform_device *pdev) | 950 | static int rfbi_bind(struct device *dev, struct device *master, void *data) |
| 950 | { | 951 | { |
| 952 | struct platform_device *pdev = to_platform_device(dev); | ||
| 951 | u32 rev; | 953 | u32 rev; |
| 952 | struct resource *rfbi_mem; | 954 | struct resource *rfbi_mem; |
| 953 | struct clk *clk; | 955 | struct clk *clk; |
| @@ -1005,8 +1007,10 @@ err_runtime_get: | |||
| 1005 | return r; | 1007 | return r; |
| 1006 | } | 1008 | } |
| 1007 | 1009 | ||
| 1008 | static int __exit omap_rfbihw_remove(struct platform_device *pdev) | 1010 | static void rfbi_unbind(struct device *dev, struct device *master, void *data) |
| 1009 | { | 1011 | { |
| 1012 | struct platform_device *pdev = to_platform_device(dev); | ||
| 1013 | |||
| 1010 | rfbi_uninit_output(pdev); | 1014 | rfbi_uninit_output(pdev); |
| 1011 | 1015 | ||
| 1012 | pm_runtime_disable(&pdev->dev); | 1016 | pm_runtime_disable(&pdev->dev); |
| @@ -1014,6 +1018,22 @@ static int __exit omap_rfbihw_remove(struct platform_device *pdev) | |||
| 1014 | return 0; | 1018 | return 0; |
| 1015 | } | 1019 | } |
| 1016 | 1020 | ||
| 1021 | static const struct component_ops rfbi_component_ops = { | ||
| 1022 | .bind = rfbi_bind, | ||
| 1023 | .unbind = rfbi_unbind, | ||
| 1024 | }; | ||
| 1025 | |||
| 1026 | static int rfbi_probe(struct platform_device *pdev) | ||
| 1027 | { | ||
| 1028 | return component_add(&pdev->dev, &rfbi_component_ops); | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | static int rfbi_remove(struct platform_device *pdev) | ||
| 1032 | { | ||
| 1033 | component_del(&pdev->dev, &rfbi_component_ops); | ||
| 1034 | return 0; | ||
| 1035 | } | ||
| 1036 | |||
| 1017 | static int rfbi_runtime_suspend(struct device *dev) | 1037 | static int rfbi_runtime_suspend(struct device *dev) |
| 1018 | { | 1038 | { |
| 1019 | dispc_runtime_put(); | 1039 | dispc_runtime_put(); |
| @@ -1038,8 +1058,8 @@ static const struct dev_pm_ops rfbi_pm_ops = { | |||
| 1038 | }; | 1058 | }; |
| 1039 | 1059 | ||
| 1040 | static struct platform_driver omap_rfbihw_driver = { | 1060 | static struct platform_driver omap_rfbihw_driver = { |
| 1041 | .probe = omap_rfbihw_probe, | 1061 | .probe = rfbi_probe, |
| 1042 | .remove = __exit_p(omap_rfbihw_remove), | 1062 | .remove = rfbi_remove, |
| 1043 | .driver = { | 1063 | .driver = { |
| 1044 | .name = "omapdss_rfbi", | 1064 | .name = "omapdss_rfbi", |
| 1045 | .pm = &rfbi_pm_ops, | 1065 | .pm = &rfbi_pm_ops, |
| @@ -1052,7 +1072,7 @@ int __init rfbi_init_platform_driver(void) | |||
| 1052 | return platform_driver_register(&omap_rfbihw_driver); | 1072 | return platform_driver_register(&omap_rfbihw_driver); |
| 1053 | } | 1073 | } |
| 1054 | 1074 | ||
| 1055 | void __exit rfbi_uninit_platform_driver(void) | 1075 | void rfbi_uninit_platform_driver(void) |
| 1056 | { | 1076 | { |
| 1057 | platform_driver_unregister(&omap_rfbihw_driver); | 1077 | platform_driver_unregister(&omap_rfbihw_driver); |
| 1058 | } | 1078 | } |
diff --git a/drivers/video/fbdev/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/dss/sdi.c index 5c2ccab5a958..5843580a1deb 100644 --- a/drivers/video/fbdev/omap2/dss/sdi.c +++ b/drivers/video/fbdev/omap2/dss/sdi.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| 28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 29 | #include <linux/of.h> | 29 | #include <linux/of.h> |
| 30 | #include <linux/component.h> | ||
| 30 | 31 | ||
| 31 | #include <video/omapdss.h> | 32 | #include <video/omapdss.h> |
| 32 | #include "dss.h" | 33 | #include "dss.h" |
| @@ -350,15 +351,17 @@ static void sdi_init_output(struct platform_device *pdev) | |||
| 350 | omapdss_register_output(out); | 351 | omapdss_register_output(out); |
| 351 | } | 352 | } |
| 352 | 353 | ||
| 353 | static void __exit sdi_uninit_output(struct platform_device *pdev) | 354 | static void sdi_uninit_output(struct platform_device *pdev) |
| 354 | { | 355 | { |
| 355 | struct omap_dss_device *out = &sdi.output; | 356 | struct omap_dss_device *out = &sdi.output; |
| 356 | 357 | ||
| 357 | omapdss_unregister_output(out); | 358 | omapdss_unregister_output(out); |
| 358 | } | 359 | } |
| 359 | 360 | ||
| 360 | static int omap_sdi_probe(struct platform_device *pdev) | 361 | static int sdi_bind(struct device *dev, struct device *master, void *data) |
| 361 | { | 362 | { |
| 363 | struct platform_device *pdev = to_platform_device(dev); | ||
| 364 | |||
| 362 | sdi.pdev = pdev; | 365 | sdi.pdev = pdev; |
| 363 | 366 | ||
| 364 | sdi_init_output(pdev); | 367 | sdi_init_output(pdev); |
| @@ -366,16 +369,32 @@ static int omap_sdi_probe(struct platform_device *pdev) | |||
| 366 | return 0; | 369 | return 0; |
| 367 | } | 370 | } |
| 368 | 371 | ||
| 369 | static int __exit omap_sdi_remove(struct platform_device *pdev) | 372 | static void sdi_unbind(struct device *dev, struct device *master, void *data) |
| 370 | { | 373 | { |
| 374 | struct platform_device *pdev = to_platform_device(dev); | ||
| 375 | |||
| 371 | sdi_uninit_output(pdev); | 376 | sdi_uninit_output(pdev); |
| 377 | } | ||
| 378 | |||
| 379 | static const struct component_ops sdi_component_ops = { | ||
| 380 | .bind = sdi_bind, | ||
| 381 | .unbind = sdi_unbind, | ||
| 382 | }; | ||
| 372 | 383 | ||
| 384 | static int sdi_probe(struct platform_device *pdev) | ||
| 385 | { | ||
| 386 | return component_add(&pdev->dev, &sdi_component_ops); | ||
| 387 | } | ||
| 388 | |||
| 389 | static int sdi_remove(struct platform_device *pdev) | ||
| 390 | { | ||
| 391 | component_del(&pdev->dev, &sdi_component_ops); | ||
| 373 | return 0; | 392 | return 0; |
| 374 | } | 393 | } |
| 375 | 394 | ||
| 376 | static struct platform_driver omap_sdi_driver = { | 395 | static struct platform_driver omap_sdi_driver = { |
| 377 | .probe = omap_sdi_probe, | 396 | .probe = sdi_probe, |
| 378 | .remove = __exit_p(omap_sdi_remove), | 397 | .remove = sdi_remove, |
| 379 | .driver = { | 398 | .driver = { |
| 380 | .name = "omapdss_sdi", | 399 | .name = "omapdss_sdi", |
| 381 | .suppress_bind_attrs = true, | 400 | .suppress_bind_attrs = true, |
| @@ -387,12 +406,12 @@ int __init sdi_init_platform_driver(void) | |||
| 387 | return platform_driver_register(&omap_sdi_driver); | 406 | return platform_driver_register(&omap_sdi_driver); |
| 388 | } | 407 | } |
| 389 | 408 | ||
| 390 | void __exit sdi_uninit_platform_driver(void) | 409 | void sdi_uninit_platform_driver(void) |
| 391 | { | 410 | { |
| 392 | platform_driver_unregister(&omap_sdi_driver); | 411 | platform_driver_unregister(&omap_sdi_driver); |
| 393 | } | 412 | } |
| 394 | 413 | ||
| 395 | int __init sdi_init_port(struct platform_device *pdev, struct device_node *port) | 414 | int sdi_init_port(struct platform_device *pdev, struct device_node *port) |
| 396 | { | 415 | { |
| 397 | struct device_node *ep; | 416 | struct device_node *ep; |
| 398 | u32 datapairs; | 417 | u32 datapairs; |
| @@ -426,7 +445,7 @@ err_datapairs: | |||
| 426 | return r; | 445 | return r; |
| 427 | } | 446 | } |
| 428 | 447 | ||
| 429 | void __exit sdi_uninit_port(struct device_node *port) | 448 | void sdi_uninit_port(struct device_node *port) |
| 430 | { | 449 | { |
| 431 | if (!sdi.port_initialized) | 450 | if (!sdi.port_initialized) |
| 432 | return; | 451 | return; |
diff --git a/drivers/video/fbdev/omap2/dss/venc.c b/drivers/video/fbdev/omap2/dss/venc.c index ef7fd925e7f2..99ca268c1cdd 100644 --- a/drivers/video/fbdev/omap2/dss/venc.c +++ b/drivers/video/fbdev/omap2/dss/venc.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/regulator/consumer.h> | 35 | #include <linux/regulator/consumer.h> |
| 36 | #include <linux/pm_runtime.h> | 36 | #include <linux/pm_runtime.h> |
| 37 | #include <linux/of.h> | 37 | #include <linux/of.h> |
| 38 | #include <linux/component.h> | ||
| 38 | 39 | ||
| 39 | #include <video/omapdss.h> | 40 | #include <video/omapdss.h> |
| 40 | 41 | ||
| @@ -802,7 +803,7 @@ static void venc_init_output(struct platform_device *pdev) | |||
| 802 | omapdss_register_output(out); | 803 | omapdss_register_output(out); |
| 803 | } | 804 | } |
| 804 | 805 | ||
| 805 | static void __exit venc_uninit_output(struct platform_device *pdev) | 806 | static void venc_uninit_output(struct platform_device *pdev) |
| 806 | { | 807 | { |
| 807 | struct omap_dss_device *out = &venc.output; | 808 | struct omap_dss_device *out = &venc.output; |
| 808 | 809 | ||
| @@ -852,8 +853,9 @@ err: | |||
| 852 | } | 853 | } |
| 853 | 854 | ||
| 854 | /* VENC HW IP initialisation */ | 855 | /* VENC HW IP initialisation */ |
| 855 | static int omap_venchw_probe(struct platform_device *pdev) | 856 | static int venc_bind(struct device *dev, struct device *master, void *data) |
| 856 | { | 857 | { |
| 858 | struct platform_device *pdev = to_platform_device(dev); | ||
| 857 | u8 rev_id; | 859 | u8 rev_id; |
| 858 | struct resource *venc_mem; | 860 | struct resource *venc_mem; |
| 859 | int r; | 861 | int r; |
| @@ -912,12 +914,28 @@ err_runtime_get: | |||
| 912 | return r; | 914 | return r; |
| 913 | } | 915 | } |
| 914 | 916 | ||
| 915 | static int __exit omap_venchw_remove(struct platform_device *pdev) | 917 | static void venc_unbind(struct device *dev, struct device *master, void *data) |
| 916 | { | 918 | { |
| 919 | struct platform_device *pdev = to_platform_device(dev); | ||
| 920 | |||
| 917 | venc_uninit_output(pdev); | 921 | venc_uninit_output(pdev); |
| 918 | 922 | ||
| 919 | pm_runtime_disable(&pdev->dev); | 923 | pm_runtime_disable(&pdev->dev); |
| 924 | } | ||
| 920 | 925 | ||
| 926 | static const struct component_ops venc_component_ops = { | ||
| 927 | .bind = venc_bind, | ||
| 928 | .unbind = venc_unbind, | ||
| 929 | }; | ||
| 930 | |||
| 931 | static int venc_probe(struct platform_device *pdev) | ||
| 932 | { | ||
| 933 | return component_add(&pdev->dev, &venc_component_ops); | ||
| 934 | } | ||
| 935 | |||
| 936 | static int venc_remove(struct platform_device *pdev) | ||
| 937 | { | ||
| 938 | component_del(&pdev->dev, &venc_component_ops); | ||
| 921 | return 0; | 939 | return 0; |
| 922 | } | 940 | } |
| 923 | 941 | ||
| @@ -950,7 +968,6 @@ static const struct dev_pm_ops venc_pm_ops = { | |||
| 950 | .runtime_resume = venc_runtime_resume, | 968 | .runtime_resume = venc_runtime_resume, |
| 951 | }; | 969 | }; |
| 952 | 970 | ||
| 953 | |||
| 954 | static const struct of_device_id venc_of_match[] = { | 971 | static const struct of_device_id venc_of_match[] = { |
| 955 | { .compatible = "ti,omap2-venc", }, | 972 | { .compatible = "ti,omap2-venc", }, |
| 956 | { .compatible = "ti,omap3-venc", }, | 973 | { .compatible = "ti,omap3-venc", }, |
| @@ -959,8 +976,8 @@ static const struct of_device_id venc_of_match[] = { | |||
| 959 | }; | 976 | }; |
| 960 | 977 | ||
| 961 | static struct platform_driver omap_venchw_driver = { | 978 | static struct platform_driver omap_venchw_driver = { |
| 962 | .probe = omap_venchw_probe, | 979 | .probe = venc_probe, |
| 963 | .remove = __exit_p(omap_venchw_remove), | 980 | .remove = venc_remove, |
| 964 | .driver = { | 981 | .driver = { |
| 965 | .name = "omapdss_venc", | 982 | .name = "omapdss_venc", |
| 966 | .pm = &venc_pm_ops, | 983 | .pm = &venc_pm_ops, |
| @@ -974,7 +991,7 @@ int __init venc_init_platform_driver(void) | |||
| 974 | return platform_driver_register(&omap_venchw_driver); | 991 | return platform_driver_register(&omap_venchw_driver); |
| 975 | } | 992 | } |
| 976 | 993 | ||
| 977 | void __exit venc_uninit_platform_driver(void) | 994 | void venc_uninit_platform_driver(void) |
| 978 | { | 995 | { |
| 979 | platform_driver_unregister(&omap_venchw_driver); | 996 | platform_driver_unregister(&omap_venchw_driver); |
| 980 | } | 997 | } |
