aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChandrabhanu Mahapatra <cmahapatra@ti.com>2012-07-03 02:56:51 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-08-22 04:43:03 -0400
commitdcbe765b4f7c097ceab7dabe3af29e2a02529ebf (patch)
treef1a960f2491d27ec8e803f743d402cbe6924020a /drivers
parent0b3d9cfe7d6ac9cedd2ddbb6f3415980b3cfc36e (diff)
OMAPDSS: DISPC: Cleanup cpu_is_xxxx checks
All the cpu_is checks have been moved to dispc_init_features function providing a much more generic and cleaner interface. The OMAP version and revision specific functions and data are initialized by dispc_features structure which is local to dispc.c. Signed-off-by: Chandrabhanu Mahapatra <cmahapatra@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/omap2/dss/dispc.c434
1 files changed, 279 insertions, 155 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index ff52702dfd2..0de9a7efcbc 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -81,6 +81,23 @@ struct dispc_irq_stats {
81 unsigned irqs[32]; 81 unsigned irqs[32];
82}; 82};
83 83
84struct dispc_features {
85 u8 sw_start;
86 u8 fp_start;
87 u8 bp_start;
88 u16 sw_max;
89 u16 vp_max;
90 u16 hp_max;
91 int (*calc_scaling) (enum omap_channel channel,
92 const struct omap_video_timings *mgr_timings,
93 u16 width, u16 height, u16 out_width, u16 out_height,
94 enum omap_color_mode color_mode, bool *five_taps,
95 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
96 u16 pos_x, unsigned long *core_clk);
97 unsigned long (*calc_core_clk) (enum omap_channel channel,
98 u16 width, u16 height, u16 out_width, u16 out_height);
99};
100
84static struct { 101static struct {
85 struct platform_device *pdev; 102 struct platform_device *pdev;
86 void __iomem *base; 103 void __iomem *base;
@@ -101,6 +118,8 @@ static struct {
101 bool ctx_valid; 118 bool ctx_valid;
102 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 119 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
103 120
121 const struct dispc_features *feat;
122
104#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 123#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
105 spinlock_t irq_stats_lock; 124 spinlock_t irq_stats_lock;
106 struct dispc_irq_stats irq_stats; 125 struct dispc_irq_stats irq_stats;
@@ -1939,7 +1958,18 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
1939 return core_clk; 1958 return core_clk;
1940} 1959}
1941 1960
1942static unsigned long calc_core_clk(enum omap_channel channel, u16 width, 1961static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width,
1962 u16 height, u16 out_width, u16 out_height)
1963{
1964 unsigned long pclk = dispc_mgr_pclk_rate(channel);
1965
1966 if (height > out_height && width > out_width)
1967 return pclk * 4;
1968 else
1969 return pclk * 2;
1970}
1971
1972static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width,
1943 u16 height, u16 out_width, u16 out_height) 1973 u16 height, u16 out_width, u16 out_height)
1944{ 1974{
1945 unsigned int hf, vf; 1975 unsigned int hf, vf;
@@ -1958,25 +1988,163 @@ static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
1958 hf = 2; 1988 hf = 2;
1959 else 1989 else
1960 hf = 1; 1990 hf = 1;
1961
1962 if (height > out_height) 1991 if (height > out_height)
1963 vf = 2; 1992 vf = 2;
1964 else 1993 else
1965 vf = 1; 1994 vf = 1;
1966 1995
1967 if (cpu_is_omap24xx()) { 1996 return pclk * vf * hf;
1968 if (vf > 1 && hf > 1) 1997}
1969 return pclk * 4; 1998
1970 else 1999static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width,
1971 return pclk * 2; 2000 u16 height, u16 out_width, u16 out_height)
1972 } else if (cpu_is_omap34xx()) { 2001{
1973 return pclk * vf * hf; 2002 unsigned long pclk = dispc_mgr_pclk_rate(channel);
1974 } else { 2003
1975 if (hf > 1) 2004 if (width > out_width)
1976 return DIV_ROUND_UP(pclk, out_width) * width; 2005 return DIV_ROUND_UP(pclk, out_width) * width;
1977 else 2006 else
1978 return pclk; 2007 return pclk;
2008}
2009
2010static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel,
2011 const struct omap_video_timings *mgr_timings,
2012 u16 width, u16 height, u16 out_width, u16 out_height,
2013 enum omap_color_mode color_mode, bool *five_taps,
2014 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2015 u16 pos_x, unsigned long *core_clk)
2016{
2017 int error;
2018 u16 in_width, in_height;
2019 int min_factor = min(*decim_x, *decim_y);
2020 const int maxsinglelinewidth =
2021 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2022 *five_taps = false;
2023
2024 do {
2025 in_height = DIV_ROUND_UP(height, *decim_y);
2026 in_width = DIV_ROUND_UP(width, *decim_x);
2027 *core_clk = dispc.feat->calc_core_clk(channel, in_width,
2028 in_height, out_width, out_height);
2029 error = (in_width > maxsinglelinewidth || !*core_clk ||
2030 *core_clk > dispc_core_clk_rate());
2031 if (error) {
2032 if (*decim_x == *decim_y) {
2033 *decim_x = min_factor;
2034 ++*decim_y;
2035 } else {
2036 swap(*decim_x, *decim_y);
2037 if (*decim_x < *decim_y)
2038 ++*decim_x;
2039 }
2040 }
2041 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2042
2043 if (in_width > maxsinglelinewidth) {
2044 DSSERR("Cannot scale max input width exceeded");
2045 return -EINVAL;
2046 }
2047 return 0;
2048}
2049
2050static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2051 const struct omap_video_timings *mgr_timings,
2052 u16 width, u16 height, u16 out_width, u16 out_height,
2053 enum omap_color_mode color_mode, bool *five_taps,
2054 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2055 u16 pos_x, unsigned long *core_clk)
2056{
2057 int error;
2058 u16 in_width, in_height;
2059 int min_factor = min(*decim_x, *decim_y);
2060 const int maxsinglelinewidth =
2061 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2062
2063 do {
2064 in_height = DIV_ROUND_UP(height, *decim_y);
2065 in_width = DIV_ROUND_UP(width, *decim_x);
2066 *core_clk = calc_core_clk_five_taps(channel, mgr_timings,
2067 in_width, in_height, out_width, out_height, color_mode);
2068
2069 error = check_horiz_timing_omap3(channel, mgr_timings, pos_x,
2070 in_width, in_height, out_width, out_height);
2071
2072 if (in_width > maxsinglelinewidth)
2073 if (in_height > out_height &&
2074 in_height < out_height * 2)
2075 *five_taps = false;
2076 if (!*five_taps)
2077 *core_clk = dispc.feat->calc_core_clk(channel, in_width,
2078 in_height, out_width, out_height);
2079
2080 error = (error || in_width > maxsinglelinewidth * 2 ||
2081 (in_width > maxsinglelinewidth && *five_taps) ||
2082 !*core_clk || *core_clk > dispc_core_clk_rate());
2083 if (error) {
2084 if (*decim_x == *decim_y) {
2085 *decim_x = min_factor;
2086 ++*decim_y;
2087 } else {
2088 swap(*decim_x, *decim_y);
2089 if (*decim_x < *decim_y)
2090 ++*decim_x;
2091 }
2092 }
2093 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2094
2095 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height,
2096 out_width, out_height)){
2097 DSSERR("horizontal timing too tight\n");
2098 return -EINVAL;
2099 }
2100
2101 if (in_width > (maxsinglelinewidth * 2)) {
2102 DSSERR("Cannot setup scaling");
2103 DSSERR("width exceeds maximum width possible");
2104 return -EINVAL;
2105 }
2106
2107 if (in_width > maxsinglelinewidth && *five_taps) {
2108 DSSERR("cannot setup scaling with five taps");
2109 return -EINVAL;
1979 } 2110 }
2111 return 0;
2112}
2113
2114static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel,
2115 const struct omap_video_timings *mgr_timings,
2116 u16 width, u16 height, u16 out_width, u16 out_height,
2117 enum omap_color_mode color_mode, bool *five_taps,
2118 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2119 u16 pos_x, unsigned long *core_clk)
2120{
2121 u16 in_width, in_width_max;
2122 int decim_x_min = *decim_x;
2123 u16 in_height = DIV_ROUND_UP(height, *decim_y);
2124 const int maxsinglelinewidth =
2125 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2126
2127 in_width_max = dispc_core_clk_rate() /
2128 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width);
2129 *decim_x = DIV_ROUND_UP(width, in_width_max);
2130
2131 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
2132 if (*decim_x > *x_predecim)
2133 return -EINVAL;
2134
2135 do {
2136 in_width = DIV_ROUND_UP(width, *decim_x);
2137 } while (*decim_x <= *x_predecim &&
2138 in_width > maxsinglelinewidth && ++*decim_x);
2139
2140 if (in_width > maxsinglelinewidth) {
2141 DSSERR("Cannot scale width exceeds max line width");
2142 return -EINVAL;
2143 }
2144
2145 *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height,
2146 out_width, out_height);
2147 return 0;
1980} 2148}
1981 2149
1982static int dispc_ovl_calc_scaling(enum omap_plane plane, 2150static int dispc_ovl_calc_scaling(enum omap_plane plane,
@@ -1988,12 +2156,9 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1988{ 2156{
1989 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 2157 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1990 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 2158 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1991 const int maxsinglelinewidth =
1992 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
1993 const int max_decim_limit = 16; 2159 const int max_decim_limit = 16;
1994 unsigned long core_clk = 0; 2160 unsigned long core_clk = 0;
1995 int decim_x, decim_y, error, min_factor; 2161 int decim_x, decim_y, ret;
1996 u16 in_width, in_height, in_width_max = 0;
1997 2162
1998 if (width == out_width && height == out_height) 2163 if (width == out_width && height == out_height)
1999 return 0; 2164 return 0;
@@ -2017,118 +2182,17 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2017 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); 2182 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
2018 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); 2183 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
2019 2184
2020 min_factor = min(decim_x, decim_y);
2021
2022 if (decim_x > *x_predecim || out_width > width * 8) 2185 if (decim_x > *x_predecim || out_width > width * 8)
2023 return -EINVAL; 2186 return -EINVAL;
2024 2187
2025 if (decim_y > *y_predecim || out_height > height * 8) 2188 if (decim_y > *y_predecim || out_height > height * 8)
2026 return -EINVAL; 2189 return -EINVAL;
2027 2190
2028 if (cpu_is_omap24xx()) { 2191 ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height,
2029 *five_taps = false; 2192 out_width, out_height, color_mode, five_taps, x_predecim,
2030 2193 y_predecim, &decim_x, &decim_y, pos_x, &core_clk);
2031 do { 2194 if (ret)
2032 in_height = DIV_ROUND_UP(height, decim_y); 2195 return ret;
2033 in_width = DIV_ROUND_UP(width, decim_x);
2034 core_clk = calc_core_clk(channel, in_width, in_height,
2035 out_width, out_height);
2036 error = (in_width > maxsinglelinewidth || !core_clk ||
2037 core_clk > dispc_core_clk_rate());
2038 if (error) {
2039 if (decim_x == decim_y) {
2040 decim_x = min_factor;
2041 decim_y++;
2042 } else {
2043 swap(decim_x, decim_y);
2044 if (decim_x < decim_y)
2045 decim_x++;
2046 }
2047 }
2048 } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
2049 error);
2050
2051 if (in_width > maxsinglelinewidth) {
2052 DSSERR("Cannot scale max input width exceeded");
2053 return -EINVAL;
2054 }
2055 } else if (cpu_is_omap34xx()) {
2056
2057 do {
2058 in_height = DIV_ROUND_UP(height, decim_y);
2059 in_width = DIV_ROUND_UP(width, decim_x);
2060 core_clk = calc_core_clk_five_taps(channel, mgr_timings,
2061 in_width, in_height, out_width, out_height,
2062 color_mode);
2063
2064 error = check_horiz_timing_omap3(channel, mgr_timings,
2065 pos_x, in_width, in_height, out_width,
2066 out_height);
2067
2068 if (in_width > maxsinglelinewidth)
2069 if (in_height > out_height &&
2070 in_height < out_height * 2)
2071 *five_taps = false;
2072 if (!*five_taps)
2073 core_clk = calc_core_clk(channel, in_width,
2074 in_height, out_width, out_height);
2075 error = (error || in_width > maxsinglelinewidth * 2 ||
2076 (in_width > maxsinglelinewidth && *five_taps) ||
2077 !core_clk || core_clk > dispc_core_clk_rate());
2078 if (error) {
2079 if (decim_x == decim_y) {
2080 decim_x = min_factor;
2081 decim_y++;
2082 } else {
2083 swap(decim_x, decim_y);
2084 if (decim_x < decim_y)
2085 decim_x++;
2086 }
2087 }
2088 } while (decim_x <= *x_predecim && decim_y <= *y_predecim
2089 && error);
2090
2091 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
2092 height, out_width, out_height)){
2093 DSSERR("horizontal timing too tight\n");
2094 return -EINVAL;
2095 }
2096
2097 if (in_width > (maxsinglelinewidth * 2)) {
2098 DSSERR("Cannot setup scaling");
2099 DSSERR("width exceeds maximum width possible");
2100 return -EINVAL;
2101 }
2102
2103 if (in_width > maxsinglelinewidth && *five_taps) {
2104 DSSERR("cannot setup scaling with five taps");
2105 return -EINVAL;
2106 }
2107 } else {
2108 int decim_x_min = decim_x;
2109 in_height = DIV_ROUND_UP(height, decim_y);
2110 in_width_max = dispc_core_clk_rate() /
2111 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
2112 out_width);
2113 decim_x = DIV_ROUND_UP(width, in_width_max);
2114
2115 decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
2116 if (decim_x > *x_predecim)
2117 return -EINVAL;
2118
2119 do {
2120 in_width = DIV_ROUND_UP(width, decim_x);
2121 } while (decim_x <= *x_predecim &&
2122 in_width > maxsinglelinewidth && decim_x++);
2123
2124 if (in_width > maxsinglelinewidth) {
2125 DSSERR("Cannot scale width exceeds max line width");
2126 return -EINVAL;
2127 }
2128
2129 core_clk = calc_core_clk(channel, in_width, in_height,
2130 out_width, out_height);
2131 }
2132 2196
2133 DSSDBG("required core clk rate = %lu Hz\n", core_clk); 2197 DSSDBG("required core clk rate = %lu Hz\n", core_clk);
2134 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); 2198 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
@@ -2604,24 +2668,13 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height)
2604static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2668static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2605 int vsw, int vfp, int vbp) 2669 int vsw, int vfp, int vbp)
2606{ 2670{
2607 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2671 if (hsw < 1 || hsw > dispc.feat->sw_max ||
2608 if (hsw < 1 || hsw > 64 || 2672 hfp < 1 || hfp > dispc.feat->hp_max ||
2609 hfp < 1 || hfp > 256 || 2673 hbp < 1 || hbp > dispc.feat->hp_max ||
2610 hbp < 1 || hbp > 256 || 2674 vsw < 1 || vsw > dispc.feat->sw_max ||
2611 vsw < 1 || vsw > 64 || 2675 vfp < 0 || vfp > dispc.feat->vp_max ||
2612 vfp < 0 || vfp > 255 || 2676 vbp < 0 || vbp > dispc.feat->vp_max)
2613 vbp < 0 || vbp > 255) 2677 return false;
2614 return false;
2615 } else {
2616 if (hsw < 1 || hsw > 256 ||
2617 hfp < 1 || hfp > 4096 ||
2618 hbp < 1 || hbp > 4096 ||
2619 vsw < 1 || vsw > 256 ||
2620 vfp < 0 || vfp > 4095 ||
2621 vbp < 0 || vbp > 4095)
2622 return false;
2623 }
2624
2625 return true; 2678 return true;
2626} 2679}
2627 2680
@@ -2653,19 +2706,12 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
2653 u32 timing_h, timing_v, l; 2706 u32 timing_h, timing_v, l;
2654 bool onoff, rf, ipc; 2707 bool onoff, rf, ipc;
2655 2708
2656 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2709 timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
2657 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | 2710 FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
2658 FLD_VAL(hbp-1, 27, 20); 2711 FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
2659 2712 timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
2660 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | 2713 FLD_VAL(vfp, dispc.feat->fp_start, 8) |
2661 FLD_VAL(vbp, 27, 20); 2714 FLD_VAL(vbp, dispc.feat->bp_start, 20);
2662 } else {
2663 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
2664 FLD_VAL(hbp-1, 31, 20);
2665
2666 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
2667 FLD_VAL(vbp, 31, 20);
2668 }
2669 2715
2670 dispc_write_reg(DISPC_TIMING_H(channel), timing_h); 2716 dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2671 dispc_write_reg(DISPC_TIMING_V(channel), timing_v); 2717 dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
@@ -3671,6 +3717,80 @@ static void _omap_dispc_initial_config(void)
3671 dispc_ovl_enable_zorder_planes(); 3717 dispc_ovl_enable_zorder_planes();
3672} 3718}
3673 3719
3720static const struct dispc_features omap24xx_dispc_feats __initconst = {
3721 .sw_start = 5,
3722 .fp_start = 15,
3723 .bp_start = 27,
3724 .sw_max = 64,
3725 .vp_max = 255,
3726 .hp_max = 256,
3727 .calc_scaling = dispc_ovl_calc_scaling_24xx,
3728 .calc_core_clk = calc_core_clk_24xx,
3729};
3730
3731static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
3732 .sw_start = 5,
3733 .fp_start = 15,
3734 .bp_start = 27,
3735 .sw_max = 64,
3736 .vp_max = 255,
3737 .hp_max = 256,
3738 .calc_scaling = dispc_ovl_calc_scaling_34xx,
3739 .calc_core_clk = calc_core_clk_34xx,
3740};
3741
3742static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
3743 .sw_start = 7,
3744 .fp_start = 19,
3745 .bp_start = 31,
3746 .sw_max = 256,
3747 .vp_max = 4095,
3748 .hp_max = 4096,
3749 .calc_scaling = dispc_ovl_calc_scaling_34xx,
3750 .calc_core_clk = calc_core_clk_34xx,
3751};
3752
3753static const struct dispc_features omap44xx_dispc_feats __initconst = {
3754 .sw_start = 7,
3755 .fp_start = 19,
3756 .bp_start = 31,
3757 .sw_max = 256,
3758 .vp_max = 4095,
3759 .hp_max = 4096,
3760 .calc_scaling = dispc_ovl_calc_scaling_44xx,
3761 .calc_core_clk = calc_core_clk_44xx,
3762};
3763
3764static int __init dispc_init_features(struct device *dev)
3765{
3766 const struct dispc_features *src;
3767 struct dispc_features *dst;
3768
3769 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
3770 if (!dst) {
3771 dev_err(dev, "Failed to allocate DISPC Features\n");
3772 return -ENOMEM;
3773 }
3774
3775 if (cpu_is_omap24xx()) {
3776 src = &omap24xx_dispc_feats;
3777 } else if (cpu_is_omap34xx()) {
3778 if (omap_rev() < OMAP3430_REV_ES3_0)
3779 src = &omap34xx_rev1_0_dispc_feats;
3780 else
3781 src = &omap34xx_rev3_0_dispc_feats;
3782 } else if (cpu_is_omap44xx()) {
3783 src = &omap44xx_dispc_feats;
3784 } else {
3785 return -ENODEV;
3786 }
3787
3788 memcpy(dst, src, sizeof(*dst));
3789 dispc.feat = dst;
3790
3791 return 0;
3792}
3793
3674/* DISPC HW IP initialisation */ 3794/* DISPC HW IP initialisation */
3675static int __init omap_dispchw_probe(struct platform_device *pdev) 3795static int __init omap_dispchw_probe(struct platform_device *pdev)
3676{ 3796{
@@ -3681,6 +3801,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
3681 3801
3682 dispc.pdev = pdev; 3802 dispc.pdev = pdev;
3683 3803
3804 r = dispc_init_features(&dispc.pdev->dev);
3805 if (r)
3806 return r;
3807
3684 spin_lock_init(&dispc.irq_lock); 3808 spin_lock_init(&dispc.irq_lock);
3685 3809
3686#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 3810#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS